@@ -10,90 +10,219 @@ require('dotenv').config({ path: '../../../.env' });
1010
1111/**
1212 * Step 1. GET /assets API
13- * Step 2. GET /constants API
13+ * Retrieves:
14+ * - The list of assets supported for burning
15+ *
16+ * Step 2. GET /{token}/constants API
17+ * Retrieves:
18+ * - Treasury Account Wallet ID for the specified stablecoin
19+ *
1420 * Step 3. POST /order API
15- * Step 4. sendMany
21+ * Creates a Burn Order with the specified parameters
22+ *
23+ * Step 4. Transfer the assets to be burnt, to the treasury account
24+ * Initiates the send transaction to the Treasury Account using sendMany
1625 */
1726
18- // Add the parameters here
27+ // IMPORTANT - Update the parameters here
1928const environment = 'test' ;
2029const accessToken = '' ;
2130const enterpriseId = '' ;
2231const walletId = '' ; // GoAccount Wallet ID
2332const walletPassphrase = '' ; // Wallet passphrase
24- const usdcoin = 'tfiatusd' ;
25- const stablecoin = 'tbsc:usd1' ;
26- const ofcStablecoin = 'ofctbsc:usd1' ;
27- const fromAmount = '3000000000000000000' ; // in base units, e.g., 3000000000000000000 for 3 TBSC:USD1
2833
34+ const usdcoin = 'tfiatusd' ; // USD asset token
35+ const stablecoin = 'tbsc:usd1' ; // Stablecoin to burn
36+ const ofcStablecoin = `ofc${ stablecoin } ` ; // ofc stablecoin (for initiating the send from the specified GoAccount wallet to the Treasury Go Account)
37+ const fromAmountInFullUnits = '100' ; // Amount in full units of the stablecoin (3 tbsc:usd1) - Must be an integer
38+ // Note: fromAmount will be calculated dynamically using asset decimals
39+
40+ // Initialize BitGo SDK
2941const bitgo = new BitGoJS . BitGo ( { env : environment } ) ;
3042bitgo . authenticateWithAccessToken ( { accessToken : accessToken } ) ;
31-
3243const basecoin = bitgo . coin ( ofcStablecoin ) ;
3344
45+ function createStablecoinUrl ( path : string ) : string {
46+ return common . Environments [ bitgo . getEnv ( ) ] . uri + '/api/stablecoin/v1' + path ;
47+ }
48+
49+ /**
50+ * Fetch treasury wallet ID from the constants API
51+ * @param token - The stablecoin token to get constants for
52+ * @returns The treasury account wallet ID
53+ */
54+ async function fetchTreasuryWalletId ( token : string ) : Promise < string > {
55+ console . log ( `\n🔍 STEP 2: Fetching treasury wallet ID from constants API for ${ token } ...` ) ;
56+ const constants = await bitgo . get ( createStablecoinUrl ( `/${ token } /constants` ) ) ;
57+ const treasuryAccountWalletId = constants . body . trustAccountWalletId ;
58+
59+ if ( ! treasuryAccountWalletId ) {
60+ throw new Error ( `Treasury account wallet ID not found in constants for ${ token } ` ) ;
61+ }
62+
63+ console . log ( `🏦 Treasury Account Wallet ID (from constants): ${ treasuryAccountWalletId } ` ) ;
64+ return treasuryAccountWalletId ;
65+ }
66+
67+ /**
68+ * Main function to execute the stablecoin burn order process
69+ */
3470async function main ( ) {
3571 try {
36- // Custom API path helper function
37- const stablecoinUrl = ( path : string ) => {
38- return common . Environments [ bitgo . getEnv ( ) ] . uri + '/api/stablecoin/v1' + path ;
39- } ;
40-
41- // STEP - 1: Gets the list of assets
42- const assets = await bitgo . get ( stablecoinUrl ( '/assets' ) ) ;
43- console . log ( 'assets:' , assets . body ) ;
44-
45- // Finds the USD and Stablecoin assets from above response to use in initiating the burn order
46- const usdAsset = assets . body . find ( ( asset : any ) => asset . token === usdcoin ) ;
47- const stablecoinAsset = assets . body . find ( ( asset : any ) => asset . token === stablecoin ) ;
48- if ( ! usdAsset || ! stablecoinAsset ) {
49- throw new Error ( `Asset ${ usdcoin } /${ stablecoin } not found` ) ;
50- }
51-
52- // STEP - 2: Gets the constants for the stablecoin
53- const constants = await bitgo . get ( stablecoinUrl ( `/${ stablecoin } /constants` ) ) . send ( ) ;
54- console . log ( 'constants:' , constants . body ) ;
55- // Extract the treasury account wallet ID from the constants response
56- const trustAccountWalletId = constants . body . trustAccountWalletId ;
57- if ( ! trustAccountWalletId ) {
58- throw new Error ( `Trust account wallet ID not found for ${ stablecoin } ` ) ;
59- }
72+ console . log ( '🚀 Starting Stablecoin Burn Order Process...' ) ;
73+ console . log ( '=' . repeat ( 50 ) ) ;
74+ console . log ( `Environment: ${ environment } ` ) ;
75+ console . log ( `Stablecoin: ${ stablecoin } ` ) ;
76+ console . log ( `Amount to burn: ${ fromAmountInFullUnits } full units` ) ;
77+ console . log ( '=' . repeat ( 50 ) ) ;
6078
61- // STEP - 3: Initiates the burn order
62- const orderRequestBody = {
63- sourceWalletId : walletId ,
64- destinationWalletId : walletId ,
65- destinationType : "go_account" ,
66- fromAssetId : stablecoinAsset . id ,
67- toAssetId : usdAsset . id ,
68- fromAmount,
69- type : "burn" ,
70- } ;
71- const postOrderResponse = await bitgo . post ( stablecoinUrl ( `/enterprise/${ enterpriseId } /order` ) ) . send ( orderRequestBody ) ;
72- const newOrder = postOrderResponse . body ;
73- console . log ( 'Order created:' , newOrder ) ;
74-
75- // STEP - 4: Sends the transaction to the Treasury Account using sendMany
76- const walletInstance = await basecoin . wallets ( ) . get ( { id : walletId } ) ;
77- const transaction = await walletInstance . sendMany ( {
78- recipients : [
79- {
80- address : trustAccountWalletId ,
81- amount : fromAmount ,
82- }
83- ] ,
84- sequenceId : newOrder . id , // IMPORTANT: Use the order ID as the sequence ID
85- walletPassphrase,
86- } ) ;
87- console . log ( 'Burn order process completed successfully!' ) ;
88- console . log ( 'New Transaction:' , JSON . stringify ( transaction , null , 4 ) ) ;
89-
90- const order = await bitgo . get ( stablecoinUrl ( `/enterprise/${ enterpriseId } /orders?ids=${ newOrder . id } ` ) ) . send ( ) ;
91- console . log ( 'Order details:' , JSON . stringify ( order . body , null , 4 ) ) ;
79+ // Execute the burn order process step by step
80+ const { usdAsset, stablecoinAsset, fromAmount } = await fetchAndValidateAssets ( ) ;
81+ const treasuryAccountWalletId = await fetchTreasuryWalletId ( stablecoin ) ;
82+ const newOrder = await createBurnOrder ( stablecoinAsset , usdAsset , fromAmount ) ;
83+ await sendTokensToTreasury ( treasuryAccountWalletId , newOrder . id , fromAmount ) ;
84+ const order = await fetchOrderDetails ( newOrder . id ) ;
9285
86+ displayOrderSummary ( order . id , order . status , order . fromAmount ) ;
9387 } catch ( error ) {
94- console . error ( 'Error in burn order process:' , error ) ;
88+ console . log ( '\n❌ ERROR: Burn order process failed!' ) ;
89+ console . log ( '=' . repeat ( 50 ) ) ;
90+ console . error ( `💥 Error: ${ error instanceof Error ? error . message : 'Unknown error' } ` ) ;
91+
92+ if ( error instanceof Error && error . stack ) {
93+ console . log ( '\n🔍 Stack trace:' ) ;
94+ console . error ( error . stack ) ;
95+ }
96+
97+ console . log ( '=' . repeat ( 50 ) ) ;
9598 throw error ;
9699 }
97100}
98101
102+ /**
103+ * Fetch and validate supported assets for the burn operation
104+ * @returns Object containing USD and stablecoin asset information with calculated amount
105+ */
106+ async function fetchAndValidateAssets ( ) {
107+ console . log ( '\n🔍 STEP 1: Fetching available assets...' ) ;
108+
109+ const assets = await bitgo . get ( createStablecoinUrl ( '/assets' ) ) ;
110+ console . log ( `✅ Found ${ assets . body . length } assets` ) ;
111+
112+ const usdAsset = assets . body . find ( ( asset : any ) => asset . token === usdcoin ) ;
113+ const stablecoinAsset = assets . body . find ( ( asset : any ) => asset . token === stablecoin ) ;
114+
115+ if ( ! usdAsset || ! stablecoinAsset ) {
116+ throw new Error ( `Required assets not found: ${ usdcoin } /${ stablecoin } ` ) ;
117+ }
118+
119+ console . log ( `📋 USD Asset: ${ usdAsset . token } (ID: ${ usdAsset . id } )` ) ;
120+ console . log ( `🪙 Stablecoin Asset: ${ stablecoinAsset . token } (ID: ${ stablecoinAsset . id } )` ) ;
121+
122+ // Calculate fromAmount using stablecoin asset decimals
123+ const decimals = stablecoinAsset . decimals ;
124+
125+ if ( decimals === undefined ) {
126+ throw new Error ( `Decimals not found for ${ stablecoin } ` ) ;
127+ }
128+
129+ // Calculate fromAmount using asset decimals
130+ const fromAmount = ( parseInt ( fromAmountInFullUnits , 10 ) * Math . pow ( 10 , decimals ) ) . toString ( ) ;
131+
132+ console . log ( `💰 Amount Calculation:` ) ;
133+ console . log ( ` • Full Units: ${ fromAmountInFullUnits } ${ stablecoinAsset . token } ` ) ;
134+ console . log ( ` • Decimals: ${ decimals } ` ) ;
135+ console . log ( ` • Base Units: ${ fromAmount } ` ) ;
136+
137+ return { usdAsset, stablecoinAsset, fromAmount } ;
138+ }
139+
140+ /**
141+ * Create a burn order with the specified parameters
142+ * @param stablecoinAsset - The stablecoin asset to burn
143+ * @param usdAsset - The USD asset to receive
144+ * @param fromAmount - The amount in base units to burn
145+ * @returns The created order object
146+ */
147+ async function createBurnOrder ( stablecoinAsset : any , usdAsset : any , fromAmount : string ) {
148+ console . log ( '\n🔥 STEP 3: Creating burn order...' ) ;
149+
150+ const orderRequestBody = {
151+ sourceWalletId : walletId ,
152+ destinationWalletId : walletId ,
153+ destinationType : 'go_account' ,
154+ fromAssetId : stablecoinAsset . id ,
155+ toAssetId : usdAsset . id ,
156+ fromAmount,
157+ type : 'burn' ,
158+ } ;
159+
160+ console . log ( '📝 Order Request Details:' ) ;
161+ console . log ( ` • Type: ${ orderRequestBody . type } ` ) ;
162+ console . log ( ` • From Asset: ${ stablecoin } → ${ usdcoin } ` ) ;
163+ console . log ( ` • Amount: ${ fromAmount } (base units)` ) ;
164+
165+ const postOrderResponse = await bitgo
166+ . post ( createStablecoinUrl ( `/enterprise/${ enterpriseId } /order` ) )
167+ . send ( orderRequestBody ) ;
168+ const order = postOrderResponse . body ;
169+
170+ console . log ( `✅ Burn order created successfully!` ) ;
171+ console . log ( ` • Order ID: ${ order . id } ` ) ;
172+
173+ return order ;
174+ }
175+
176+ /**
177+ * Send stablecoin tokens to the treasury account for burning
178+ * @param treasuryAccountWalletId - The treasury wallet ID to send tokens to
179+ * @param orderId - The order ID to use as sequence ID
180+ * @param fromAmount - The amount in base units of stablecoin to send
181+ * @returns The transaction object
182+ */
183+ async function sendTokensToTreasury ( treasuryAccountWalletId : string , orderId : string , fromAmount : string ) {
184+ console . log ( '\n💸 STEP 4: Sending stablecoin to treasury account...' ) ;
185+
186+ const walletInstance = await basecoin . wallets ( ) . get ( { id : walletId } ) ;
187+
188+ console . log ( '🔄 Initiating transaction...' ) ;
189+ console . log ( ` • From Wallet: ${ walletId } ` ) ;
190+ console . log ( ` • To Treasury: ${ treasuryAccountWalletId } ` ) ;
191+ console . log ( ` • Amount: ${ fromAmount } (base units)` ) ;
192+ console . log ( ` • Sequence ID: ${ orderId } ` ) ;
193+
194+ const transaction = await walletInstance . sendMany ( {
195+ recipients : [
196+ {
197+ address : treasuryAccountWalletId ,
198+ amount : fromAmount ,
199+ } ,
200+ ] ,
201+ sequenceId : orderId , // IMPORTANT - Use order ID as sequence ID for tracking
202+ walletPassphrase,
203+ } ) ;
204+
205+ console . log ( '✅ Transaction sent successfully!' ) ;
206+
207+ return transaction ;
208+ }
209+
210+ async function fetchOrderDetails ( orderId : string ) {
211+ console . log ( '\n🔍 STEP 5: Fetching final order details...' ) ;
212+ const orderResponse = await bitgo . get ( createStablecoinUrl ( `/enterprise/${ enterpriseId } /orders/${ orderId } ` ) ) . send ( ) ;
213+ return orderResponse . body ;
214+ }
215+
216+ function displayOrderSummary ( orderId : string , status : string , fromAmount : string ) {
217+ console . log ( '\n🎉 BURN ORDER INITIATION COMPLETED SUCCESSFULLY!' ) ;
218+ console . log ( '=' . repeat ( 50 ) ) ;
219+ console . log ( '📊 SUMMARY:' ) ;
220+ console . log ( ` • Order ID: ${ orderId } ` ) ;
221+ console . log ( ` • Type: Burn Order` ) ;
222+ console . log ( ` • Status: ${ status } ` ) ;
223+ console . log ( ` • Asset: ${ stablecoin } → ${ usdcoin } ` ) ;
224+ console . log ( ` • Amount: ${ fromAmount } base units` ) ;
225+ console . log ( '=' . repeat ( 50 ) ) ;
226+ }
227+
99228main ( ) . catch ( ( e ) => console . error ( e ) ) ;
0 commit comments