1- import { BaseCoin as CoinConfig , SolCoin } from '@bitgo/statics' ;
1+ import { BaseCoin as CoinConfig } from '@bitgo/statics' ;
22import { BuildTransactionError , TransactionType } from '@bitgo/sdk-core' ;
33import { Transaction } from './transaction' ;
44import {
@@ -19,6 +19,9 @@ export interface SendParams {
1919 address : string ;
2020 amount : string ;
2121 tokenName : string ;
22+ tokenAddress ?: string ;
23+ programId ?: string ;
24+ decimalPlaces ?: number ;
2225}
2326
2427const UNSIGNED_BIGINT_MAX = BigInt ( '18446744073709551615' ) ;
@@ -69,7 +72,7 @@ export class TokenTransferBuilder extends TransactionBuilder {
6972 * @param {string } params.tokenName - name of token that is intended to send
7073 * @returns {TransactionBuilder } This transaction builder
7174 */
72- send ( { address, amount, tokenName } : SendParams ) : this {
75+ send ( { address, amount, tokenName, tokenAddress , programId , decimalPlaces } : SendParams ) : this {
7376 validateAddress ( address , 'address' ) ;
7477 if ( ! amount || ! isValidAmount ( amount ) ) {
7578 throw new BuildTransactionError ( 'Invalid or missing amount, got: ' + amount ) ;
@@ -78,7 +81,7 @@ export class TokenTransferBuilder extends TransactionBuilder {
7881 throw new BuildTransactionError ( `input amount ${ amount } exceeds big int limit ${ UNSIGNED_BIGINT_MAX } ` ) ;
7982 }
8083
81- this . _sendParams . push ( { address, amount, tokenName : tokenName } ) ;
84+ this . _sendParams . push ( { address, amount, tokenName : tokenName , tokenAddress , programId , decimalPlaces } ) ;
8285 return this ;
8386 }
8487
@@ -92,10 +95,15 @@ export class TokenTransferBuilder extends TransactionBuilder {
9295 createAssociatedTokenAccount ( recipient : TokenAssociateRecipient ) : this {
9396 validateOwnerAddress ( recipient . ownerAddress ) ;
9497 const token = getSolTokenFromTokenName ( recipient . tokenName ) ;
95- if ( ! token ) {
98+ let tokenAddress : string ;
99+ if ( token ) {
100+ tokenAddress = token . tokenAddress ;
101+ } else if ( recipient . tokenAddress ) {
102+ tokenAddress = recipient . tokenAddress ;
103+ } else {
96104 throw new BuildTransactionError ( 'Invalid token name, got: ' + recipient . tokenName ) ;
97105 }
98- validateMintAddress ( token . tokenAddress ) ;
106+ validateMintAddress ( tokenAddress ) ;
99107
100108 this . _createAtaParams . push ( recipient ) ;
101109 return this ;
@@ -107,16 +115,35 @@ export class TokenTransferBuilder extends TransactionBuilder {
107115 const sendInstructions = await Promise . all (
108116 this . _sendParams . map ( async ( sendParams : SendParams ) : Promise < TokenTransfer > => {
109117 const coin = getSolTokenFromTokenName ( sendParams . tokenName ) ;
110- assert ( coin instanceof SolCoin ) ;
111- const sourceAddress = await getAssociatedTokenAccountAddress ( coin . tokenAddress , this . _sender ) ;
118+ let tokenAddress : string ;
119+ let tokenName : string ;
120+ let programId : string | undefined ;
121+ let decimals : number | undefined ;
122+ if ( coin ) {
123+ tokenAddress = coin . tokenAddress ;
124+ tokenName = coin . name ;
125+ programId = coin . programId ;
126+ decimals = coin . decimalPlaces ;
127+ } else if ( sendParams . tokenAddress ) {
128+ tokenAddress = sendParams . tokenAddress ;
129+ tokenName = sendParams . tokenName ;
130+ programId = sendParams . programId ;
131+ decimals = sendParams . decimalPlaces ;
132+ } else {
133+ throw new Error ( `Could not determine token information for ${ sendParams . tokenName } ` ) ;
134+ }
135+ const sourceAddress = await getAssociatedTokenAccountAddress ( tokenAddress , this . _sender ) ;
112136 return {
113137 type : InstructionBuilderTypes . TokenTransfer ,
114138 params : {
115139 fromAddress : this . _sender ,
116140 toAddress : sendParams . address ,
117141 amount : sendParams . amount ,
118- tokenName : coin . name ,
142+ tokenName : tokenName ,
119143 sourceAddress : sourceAddress ,
144+ tokenAddress : tokenAddress ,
145+ programId : programId ,
146+ decimalPlaces : decimals ,
120147 } ,
121148 } ;
122149 } )
@@ -127,20 +154,35 @@ export class TokenTransferBuilder extends TransactionBuilder {
127154 const createAtaInstructions = await Promise . all (
128155 uniqueCreateAtaParams . map ( async ( recipient : TokenAssociateRecipient ) : Promise < AtaInit > => {
129156 const coin = getSolTokenFromTokenName ( recipient . tokenName ) ;
130- assert ( coin instanceof SolCoin ) ;
157+ let tokenAddress : string ;
158+ let tokenName : string ;
159+ let programId : string | undefined ;
160+ if ( coin ) {
161+ tokenName = coin . name ;
162+ tokenAddress = coin . tokenAddress ;
163+ programId = coin . programId ;
164+ } else if ( recipient . tokenAddress ) {
165+ tokenName = recipient . tokenName ;
166+ tokenAddress = recipient . tokenAddress ;
167+ programId = recipient . programId ;
168+ } else {
169+ throw new Error ( `Could not determine token information for ${ recipient . tokenName } ` ) ;
170+ }
171+
131172 // Use the provided ataAddress if it exists, otherwise calculate it
132173 let ataAddress = recipient . ataAddress ;
133174 if ( ! ataAddress ) {
134- ataAddress = await getAssociatedTokenAccountAddress ( coin . tokenAddress , recipient . ownerAddress ) ;
175+ ataAddress = await getAssociatedTokenAccountAddress ( tokenAddress , recipient . ownerAddress ) ;
135176 }
136177 return {
137178 type : InstructionBuilderTypes . CreateAssociatedTokenAccount ,
138179 params : {
139180 ownerAddress : recipient . ownerAddress ,
140- tokenName : coin . name ,
141- mintAddress : coin . tokenAddress ,
181+ mintAddress : tokenAddress ,
142182 ataAddress,
143183 payerAddress : this . _sender ,
184+ tokenName : tokenName ,
185+ programId : programId ,
144186 } ,
145187 } ;
146188 } )
0 commit comments