@@ -10,90 +10,219 @@ require('dotenv').config({ path: '../../../.env' });
10
10
11
11
/**
12
12
* 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
+ *
14
20
* 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
16
25
*/
17
26
18
- // Add the parameters here
27
+ // IMPORTANT - Update the parameters here
19
28
const environment = 'test' ;
20
29
const accessToken = '' ;
21
30
const enterpriseId = '' ;
22
31
const walletId = '' ; // GoAccount Wallet ID
23
32
const 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
28
33
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
29
41
const bitgo = new BitGoJS . BitGo ( { env : environment } ) ;
30
42
bitgo . authenticateWithAccessToken ( { accessToken : accessToken } ) ;
31
-
32
43
const basecoin = bitgo . coin ( ofcStablecoin ) ;
33
44
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
+ */
34
70
async function main ( ) {
35
71
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 ) ) ;
60
78
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 ) ;
92
85
86
+ displayOrderSummary ( order . id , order . status , order . fromAmount ) ;
93
87
} 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 ) ) ;
95
98
throw error ;
96
99
}
97
100
}
98
101
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
+
99
228
main ( ) . catch ( ( e ) => console . error ( e ) ) ;
0 commit comments