Skip to content

Commit bb8ebb0

Browse files
committed
Add pmp IDL upload
1 parent e5a3ea4 commit bb8ebb0

3 files changed

Lines changed: 210 additions & 1 deletion

File tree

metadata-upload/action.yaml

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
name: "Upload Metadata"
2+
description: "Uploads metadata (IDL, security, etc.) to a program via the program-metadata program"
3+
inputs:
4+
program-id:
5+
description: "The program address to attach metadata to"
6+
required: true
7+
idl-path:
8+
description: "Path to the IDL or metadata JSON file (required for direct upload, ignored when using buffer)"
9+
required: false
10+
seed:
11+
description: "Metadata seed type (e.g. idl, security)"
12+
required: false
13+
default: "idl"
14+
rpc-url:
15+
description: "Solana RPC URL"
16+
required: true
17+
keypair:
18+
description: "The keypair to use (must be the program upgrade authority for canonical metadata)"
19+
required: true
20+
buffer:
21+
description: "Buffer address to use instead of direct file upload (for Squads workflow)"
22+
required: false
23+
close-buffer:
24+
description: "Address to receive rent when closing the buffer after use. Set to 'true' to send to the payer."
25+
required: false
26+
priority-fees:
27+
description: "Priority fees in micro-lamports per compute unit"
28+
required: false
29+
default: "100000"
30+
export:
31+
description: "Export transactions instead of executing (provide a Squads vault address to override authority)"
32+
required: false
33+
export-encoding:
34+
description: "Encoding for exported transactions (none, utf8, base58, base64)"
35+
required: false
36+
default: "base64"
37+
38+
runs:
39+
using: "composite"
40+
steps:
41+
- name: Write keypair
42+
shell: bash
43+
run: echo "$DEPLOY_KEYPAIR" > ./deploy-keypair.json && chmod 600 ./deploy-keypair.json
44+
env:
45+
DEPLOY_KEYPAIR: ${{ inputs.keypair }}
46+
47+
- name: Upload metadata
48+
uses: nick-fields/retry@v2
49+
with:
50+
timeout_minutes: 10
51+
max_attempts: 50
52+
shell: bash
53+
command: |
54+
CMD="npx @solana-program/program-metadata@latest write"
55+
CMD="$CMD ${{ inputs.seed }}"
56+
CMD="$CMD ${{ inputs.program-id }}"
57+
58+
if [ -n "${{ inputs.buffer }}" ]; then
59+
CMD="$CMD --buffer ${{ inputs.buffer }}"
60+
echo "Writing metadata from buffer ${{ inputs.buffer }}..."
61+
elif [ -n "${{ inputs.idl-path }}" ]; then
62+
CMD="$CMD ${{ inputs.idl-path }}"
63+
echo "Writing metadata from file ${{ inputs.idl-path }}..."
64+
else
65+
echo "Error: Either idl-path or buffer must be provided"
66+
exit 1
67+
fi
68+
69+
CMD="$CMD --keypair ./deploy-keypair.json"
70+
CMD="$CMD --rpc ${{ inputs.rpc-url }}"
71+
CMD="$CMD --priority-fees ${{ inputs.priority-fees }}"
72+
73+
if [ -n "${{ inputs.close-buffer }}" ]; then
74+
if [ "${{ inputs.close-buffer }}" = "true" ]; then
75+
CMD="$CMD --close-buffer"
76+
else
77+
CMD="$CMD --close-buffer ${{ inputs.close-buffer }}"
78+
fi
79+
fi
80+
81+
if [ -n "${{ inputs.export }}" ]; then
82+
CMD="$CMD --export ${{ inputs.export }}"
83+
CMD="$CMD --export-encoding ${{ inputs.export-encoding }}"
84+
fi
85+
86+
echo "Running: $CMD"
87+
NO_COLOR=1 $CMD
88+
89+
- name: Cleanup
90+
if: always()
91+
shell: bash
92+
run: rm -f ./deploy-keypair.json

readme.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ It is highly recommended to use the squads integration for program deployments.
1212
- ✅ Program deploys for both devnet and mainnet
1313
- ✅ Compute budget optimization
1414
- ✅ Retry mechanisms for RPC failures
15+
- ✅ Program Metadata IDL uploads (alternative to Anchor IDL)
1516

1617
### How to use
1718

@@ -107,11 +108,44 @@ Customize the workflow to your needs!
107108
- `keypair`: Deployer keypair
108109
- `idl-authority`: Authority for IDL updates
109110

111+
### Program Metadata (IDL Upload via program-metadata program)
112+
113+
These actions use the [program-metadata](https://github.com/solana-program/program-metadata) program to attach metadata (IDL, security.txt, etc.) to any Solana program. This is the newer alternative to Anchor's built-in IDL commands and supports any program, not just Anchor programs.
114+
115+
- `metadata-upload`: Writes metadata directly to a program or from a pre-created buffer
116+
- Supports any seed type (idl, security, or custom)
117+
- Handles both direct upload and Squads multisig workflows
118+
- Can export transactions for Squads signing
119+
- Inputs:
120+
- `program-id`: The program address
121+
- `idl-path`: Path to the metadata file (for direct upload)
122+
- `seed`: Metadata seed type (default: "idl")
123+
- `rpc-url`: Solana RPC endpoint
124+
- `keypair`: Deployer/authority keypair
125+
- `buffer`: Buffer address (for Squads workflow, instead of direct file upload)
126+
- `close-buffer`: Address to receive rent when closing buffer, or "true" for payer
127+
- `priority-fees`: Priority fees in micro-lamports (default: 100000)
128+
- `export`: Export transactions for multisig (provide vault address)
129+
- `export-encoding`: Encoding for exported transactions (default: base64)
130+
131+
- `write-metadata-buffer`: Creates a program-metadata buffer and transfers authority (for Squads multisig workflow)
132+
- Creates buffer with metadata content
133+
- Transfers buffer authority to the Squads vault
134+
- Outputs the buffer address for use in `metadata-upload`
135+
- Inputs:
136+
- `idl-path`: Path to the metadata file
137+
- `rpc-url`: Solana RPC endpoint
138+
- `keypair`: Keypair for buffer creation
139+
- `buffer-authority`: Address to set as buffer authority (e.g. Squads vault)
140+
- `priority-fees`: Priority fees in micro-lamports (default: 100000)
141+
- Outputs:
142+
- `buffer`: Created buffer address
143+
110144
### Additional Actions
111145

112146
- `build-anchor`: Specialized Anchor program builder
113147
- `program-upgrade`: Handles the exteding of the program account in case the program is getting bigger and either sets the buffer or skips that in case of squads deploy
114-
- `idl-upload`: Either sets the IDL buffer or skips that in case of squads deploy
148+
- `idl-upload`: Either sets the Anchor IDL buffer or skips that in case of squads deploy
115149
- `verify-build`: Verifies on-chain programs match source using solana-verify andthe osec api
116150

117151
## 📝 Todo List
@@ -143,6 +177,7 @@ Customize the workflow to your needs!
143177

144178
- [x] Add running tests
145179
- Research support for different test frameworks
180+
- [x] Add program-metadata IDL upload support
146181
- [ ] Add Codama support
147182
- [ ] Add to solana helpers or mucho -> release
148183
- [ ] Write guide and record video

write-metadata-buffer/action.yaml

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
name: "Write Metadata Buffer"
2+
description: "Creates a program-metadata buffer for Squads multisig workflow"
3+
inputs:
4+
idl-path:
5+
description: "Path to the IDL or metadata JSON file"
6+
required: true
7+
rpc-url:
8+
description: "Solana RPC URL"
9+
required: true
10+
keypair:
11+
description: "The keypair to use for buffer creation"
12+
required: true
13+
buffer-authority:
14+
description: "The address to set as buffer authority (e.g. Squads vault)"
15+
required: true
16+
priority-fees:
17+
description: "Priority fees in micro-lamports per compute unit"
18+
required: false
19+
default: "100000"
20+
21+
outputs:
22+
buffer:
23+
description: "Created metadata buffer address"
24+
value: ${{ steps.create-buffer.outputs.buffer }}
25+
26+
runs:
27+
using: "composite"
28+
steps:
29+
- name: Write keypair
30+
shell: bash
31+
run: echo "$DEPLOY_KEYPAIR" > ./deploy-keypair.json && chmod 600 ./deploy-keypair.json
32+
env:
33+
DEPLOY_KEYPAIR: ${{ inputs.keypair }}
34+
35+
- name: Create metadata buffer
36+
id: create-buffer
37+
uses: nick-fields/retry@v2
38+
with:
39+
timeout_minutes: 10
40+
max_attempts: 3
41+
shell: bash
42+
command: |
43+
echo "Creating program-metadata buffer from ${{ inputs.idl-path }}..."
44+
45+
OUTPUT=$(NO_COLOR=1 npx @solana-program/program-metadata@latest create-buffer \
46+
"${{ inputs.idl-path }}" \
47+
--keypair ./deploy-keypair.json \
48+
--rpc "${{ inputs.rpc-url }}" \
49+
--priority-fees ${{ inputs.priority-fees }} 2>&1)
50+
51+
echo "$OUTPUT"
52+
53+
BUFFER=$(echo "$OUTPUT" | grep -i "buffer:" | head -1 | grep -oE '[1-9A-HJ-NP-Za-km-z]{32,44}')
54+
if [ -z "$BUFFER" ]; then
55+
echo "Error: Could not extract buffer address from output"
56+
exit 1
57+
fi
58+
59+
echo "Found buffer: $BUFFER"
60+
echo "buffer=$BUFFER" >> $GITHUB_OUTPUT
61+
62+
- name: Transfer buffer authority
63+
if: steps.create-buffer.outputs.buffer != ''
64+
uses: nick-fields/retry@v2
65+
with:
66+
timeout_minutes: 5
67+
max_attempts: 3
68+
shell: bash
69+
command: |
70+
BUFFER="${{ steps.create-buffer.outputs.buffer }}"
71+
echo "Transferring buffer authority for $BUFFER to ${{ inputs.buffer-authority }}"
72+
73+
NO_COLOR=1 npx @solana-program/program-metadata@latest set-buffer-authority "$BUFFER" \
74+
--new-authority ${{ inputs.buffer-authority }} \
75+
--keypair ./deploy-keypair.json \
76+
--rpc "${{ inputs.rpc-url }}" \
77+
--priority-fees ${{ inputs.priority-fees }}
78+
79+
- name: Cleanup
80+
if: always()
81+
shell: bash
82+
run: rm -f ./deploy-keypair.json

0 commit comments

Comments
 (0)