11import { Command } from "commander" ;
2- import { CliContext , parseTxError } from "../utils" ;
2+ import { CliContext , executeTxWithErrorHandling } from "../utils" ;
33import { BN } from "@coral-xyz/anchor" ;
44import { CctpPolicy , publicKeyToEvmAddress } from "@glamsystems/glam-sdk" ;
55import { evmAddressToPublicKey } from "@glamsystems/glam-sdk" ;
@@ -32,8 +32,9 @@ export function installCctpCommands(program: Command, context: CliContext) {
3232 . argument ( "<domain>" , "CCTP domain" , parseInt )
3333 . argument ( "<destination_address>" , "Destination address" )
3434 . option ( "--base58" , "Address is a base58 string" )
35+ . option ( "-y, --yes" , "Skip confirmation prompt" , false )
3536 . description ( "Add a destination to the allowlist" )
36- . action ( async ( domain , destinationAddress , { base58 } ) => {
37+ . action ( async ( domain , destinationAddress , { base58, yes } ) => {
3738 const recipientPubkey = base58
3839 ? new PublicKey ( destinationAddress )
3940 : evmAddressToPublicKey ( destinationAddress ) ;
@@ -56,30 +57,31 @@ export function installCctpCommands(program: Command, context: CliContext) {
5657 }
5758
5859 cctpPolicy . allowedDestinations . push ( { domain, address : recipientPubkey } ) ;
59- try {
60- const txSig = await context . glamClient . access . setProtocolPolicy (
61- context . glamClient . extCctpProgram . programId ,
62- 0b01 ,
63- cctpPolicy . encode ( ) ,
64- context . txOptions ,
65- ) ;
66- console . log (
67- `Destination ${ destinationAddress } (domain ${ domain } ) added to allowlist:` ,
68- txSig ,
69- ) ;
70- } catch ( e ) {
71- console . error ( parseTxError ( e ) ) ;
72- process . exit ( 1 ) ;
73- }
60+ await executeTxWithErrorHandling (
61+ ( ) =>
62+ context . glamClient . access . setProtocolPolicy (
63+ context . glamClient . extCctpProgram . programId ,
64+ 0b01 ,
65+ cctpPolicy . encode ( ) ,
66+ context . txOptions ,
67+ ) ,
68+ {
69+ skip : yes ,
70+ message : `Confirm adding destination ${ destinationAddress } (domain ${ domain } ) to allowlist` ,
71+ } ,
72+ ( txSig ) =>
73+ `Destination ${ destinationAddress } (domain ${ domain } ) added to allowlist: ${ txSig } ` ,
74+ ) ;
7475 } ) ;
7576
7677 program
7778 . command ( "remove-destination" )
7879 . argument ( "<domain>" , "CCTP domain" , parseInt )
7980 . argument ( "<destination_address>" , "Destination address" )
8081 . option ( "--base58" , "Address is a base58 string" )
82+ . option ( "-y, --yes" , "Skip confirmation prompt" , false )
8183 . description ( "Remove a destination from the allowlist" )
82- . action ( async ( domain , destinationAddress , { base58 } ) => {
84+ . action ( async ( domain , destinationAddress , { base58, yes } ) => {
8385 const recipientPubkey = base58
8486 ? new PublicKey ( destinationAddress )
8587 : evmAddressToPublicKey ( destinationAddress ) ;
@@ -96,21 +98,21 @@ export function installCctpCommands(program: Command, context: CliContext) {
9698 cctpPolicy . allowedDestinations = cctpPolicy . allowedDestinations . filter (
9799 ( d ) => ! ( d . domain === domain && d . address . equals ( recipientPubkey ) ) ,
98100 ) ;
99- try {
100- const txSig = await context . glamClient . access . setProtocolPolicy (
101- context . glamClient . extCctpProgram . programId ,
102- 0b01 ,
103- cctpPolicy . encode ( ) ,
104- context . txOptions ,
105- ) ;
106- console . log (
107- `Destination ${ destinationAddress } (domain ${ domain } ) removed from allowlist:` ,
108- txSig ,
109- ) ;
110- } catch ( e ) {
111- console . error ( parseTxError ( e ) ) ;
112- process . exit ( 1 ) ;
113- }
101+ await executeTxWithErrorHandling (
102+ ( ) =>
103+ context . glamClient . access . setProtocolPolicy (
104+ context . glamClient . extCctpProgram . programId ,
105+ 0b01 ,
106+ cctpPolicy . encode ( ) ,
107+ context . txOptions ,
108+ ) ,
109+ {
110+ skip : yes ,
111+ message : `Confirm removing destination ${ destinationAddress } (domain ${ domain } ) from allowlist` ,
112+ } ,
113+ ( txSig ) =>
114+ `Destination ${ destinationAddress } (domain ${ domain } ) removed from allowlist: ${ txSig } ` ,
115+ ) ;
114116 } ) ;
115117
116118 // https://developers.circle.com/cctp/cctp-supported-blockchains#cctp-v2-supported-domains
@@ -121,52 +123,57 @@ export function installCctpCommands(program: Command, context: CliContext) {
121123 . argument ( "<destination_address>" , "EVM address" )
122124 . option ( "--base58" , "Address is a base58 string" )
123125 . option ( "--fast" , "Fast transfer (lower finality threshold)" , false )
126+ . option ( "-y, --yes" , "Skip confirmation prompt" , false )
124127 . description ( "Bridge USDC to an EVM chain" )
125- . action ( async ( amount , domain , destinationAddress , { base58, fast } ) => {
126- const recipientPubkey = base58
127- ? new PublicKey ( destinationAddress )
128- : evmAddressToPublicKey ( destinationAddress ) ;
128+ . action (
129+ async ( amount , domain , destinationAddress , { base58, fast, yes } ) => {
130+ const recipientPubkey = base58
131+ ? new PublicKey ( destinationAddress )
132+ : evmAddressToPublicKey ( destinationAddress ) ;
129133
130- const cctpPolicy = await context . glamClient . fetchProtocolPolicy (
131- context . glamClient . extCctpProgram . programId ,
132- 0b01 ,
133- CctpPolicy ,
134- ) ;
135- if (
136- cctpPolicy &&
137- ! cctpPolicy . allowedDestinations . find (
138- ( d ) => d . domain === domain && d . address . equals ( recipientPubkey ) ,
139- )
140- ) {
141- console . error (
142- `Destination (${ domain } , ${ destinationAddress } ) not in allowlist` ,
134+ const cctpPolicy = await context . glamClient . fetchProtocolPolicy (
135+ context . glamClient . extCctpProgram . programId ,
136+ 0b01 ,
137+ CctpPolicy ,
143138 ) ;
144- process . exit ( 1 ) ;
145- }
139+ if (
140+ cctpPolicy &&
141+ ! cctpPolicy . allowedDestinations . find (
142+ ( d ) => d . domain === domain && d . address . equals ( recipientPubkey ) ,
143+ )
144+ ) {
145+ console . error (
146+ `Destination (${ domain } , ${ destinationAddress } ) not in allowlist` ,
147+ ) ;
148+ process . exit ( 1 ) ;
149+ }
146150
147- const amountBN = new BN ( amount * 10 ** 6 ) ;
151+ const amountBN = new BN ( amount * 10 ** 6 ) ;
148152
149- // https://developers.circle.com/cctp/technical-guide#cctp-finality-thresholds
150- const maxFee = amountBN . mul ( new BN ( 1 ) ) . div ( new BN ( 10 ** 4 ) ) ;
151- const minFinalityThreshold = fast ? 1000 : 2000 ;
153+ // https://developers.circle.com/cctp/technical-guide#cctp-finality-thresholds
154+ const maxFee = amountBN . mul ( new BN ( 1 ) ) . div ( new BN ( 10 ** 4 ) ) ;
155+ const minFinalityThreshold = fast ? 1000 : 2000 ;
152156
153- try {
154- const txSig = await context . glamClient . cctp . bridgeUsdc (
155- amountBN ,
156- domain ,
157- recipientPubkey ,
157+ await executeTxWithErrorHandling (
158+ ( ) =>
159+ context . glamClient . cctp . bridgeUsdc (
160+ amountBN ,
161+ domain ,
162+ recipientPubkey ,
163+ {
164+ maxFee,
165+ minFinalityThreshold,
166+ } ,
167+ context . txOptions ,
168+ ) ,
158169 {
159- maxFee ,
160- minFinalityThreshold ,
170+ skip : yes ,
171+ message : `Confirm bridging ${ amount } USDC to ${ destinationAddress } (domain ${ domain } )` ,
161172 } ,
162- context . txOptions ,
173+ ( txSig ) => `USDC burned: ${ txSig } ` ,
163174 ) ;
164- console . log ( `Deposit for burn:` , txSig ) ;
165- } catch ( e ) {
166- console . error ( parseTxError ( e ) ) ;
167- process . exit ( 1 ) ;
168- }
169- } ) ;
175+ } ,
176+ ) ;
170177
171178 program
172179 . command ( "receive" )
@@ -180,24 +187,24 @@ export function installCctpCommands(program: Command, context: CliContext) {
180187 "Receive USDC from an EVM chain. Either txHash or nonce is required." ,
181188 )
182189 . action ( async ( sourceDomain , { txHash, nonce } ) => {
183- try {
184- await context . glamClient . cctp . receiveUsdc (
185- sourceDomain ,
186- {
187- txHash ,
188- nonce ,
189- } ,
190- {
191- ... context . txOptions ,
192- lookupTables : [
193- new PublicKey ( "qj4EYgsGpnRdt9rvQW3wWZR8JVaKPg9rG9EB8DNgfz8" ) , // CCTP lookup table
194- ] ,
195- } ,
196- ) ;
197- } catch ( e ) {
198- console . error ( parseTxError ( e ) ) ;
199- process . exit ( 1 ) ;
200- }
190+ await executeTxWithErrorHandling (
191+ ( ) =>
192+ context . glamClient . cctp . receiveUsdc (
193+ sourceDomain ,
194+ {
195+ txHash ,
196+ nonce ,
197+ } ,
198+ {
199+ ... context . txOptions ,
200+ lookupTables : [
201+ new PublicKey ( "qj4EYgsGpnRdt9rvQW3wWZR8JVaKPg9rG9EB8DNgfz8" ) , // CCTP lookup table
202+ ] ,
203+ } ,
204+ ) ,
205+ { skip : true } ,
206+ ( txSig ) => `Received USDC: ${ txSig } ` ,
207+ ) ;
201208 } ) ;
202209
203210 program
0 commit comments