@@ -3180,6 +3180,69 @@ describe('V2 Wallet:', function () {
31803180 intent . intentType . should . equal ( 'fillNonce' ) ;
31813181 } ) ;
31823182
3183+ it ( 'populate intent should return valid eth tokenApproval intent' , async function ( ) {
3184+ const mpcUtils = new ECDSAUtils . EcdsaUtils ( bitgo , bitgo . coin ( 'hteth' ) ) ;
3185+ const feeOptions = {
3186+ maxFeePerGas : 3000000000 ,
3187+ maxPriorityFeePerGas : 2000000000 ,
3188+ } ;
3189+ const tokenName = 'usdc' ;
3190+
3191+ const intent = mpcUtils . populateIntent ( bitgo . coin ( 'hteth' ) , {
3192+ reqId,
3193+ intentType : 'tokenApproval' ,
3194+ tokenName,
3195+ feeOptions,
3196+ } ) ;
3197+
3198+ intent . should . have . property ( 'recipients' , undefined ) ;
3199+ intent . feeOptions ! . should . deepEqual ( feeOptions ) ;
3200+ intent . tokenName ! . should . equal ( tokenName ) ;
3201+ intent . intentType . should . equal ( 'tokenApproval' ) ;
3202+ } ) ;
3203+
3204+ it ( 'populate intent should return valid polygon tokenApproval intent' , async function ( ) {
3205+ const mpcUtils = new ECDSAUtils . EcdsaUtils ( bitgo , bitgo . coin ( 'tpolygon' ) ) ;
3206+ const feeOptions = {
3207+ maxFeePerGas : 3000000000 ,
3208+ maxPriorityFeePerGas : 2000000000 ,
3209+ } ;
3210+ const tokenName = 'usdt' ;
3211+
3212+ const intent = mpcUtils . populateIntent ( bitgo . coin ( 'tpolygon' ) , {
3213+ reqId,
3214+ intentType : 'tokenApproval' ,
3215+ tokenName,
3216+ feeOptions,
3217+ } ) ;
3218+
3219+ intent . should . have . property ( 'recipients' , undefined ) ;
3220+ intent . feeOptions ! . should . deepEqual ( feeOptions ) ;
3221+ intent . tokenName ! . should . equal ( tokenName ) ;
3222+ intent . intentType . should . equal ( 'tokenApproval' ) ;
3223+ } ) ;
3224+
3225+ it ( 'populate intent should return valid bsc tokenApproval intent' , async function ( ) {
3226+ const mpcUtils = new ECDSAUtils . EcdsaUtils ( bitgo , bitgo . coin ( 'tbsc' ) ) ;
3227+ const feeOptions = {
3228+ maxFeePerGas : 3000000000 ,
3229+ maxPriorityFeePerGas : 2000000000 ,
3230+ } ;
3231+ const tokenName = 'busd' ;
3232+
3233+ const intent = mpcUtils . populateIntent ( bitgo . coin ( 'tbsc' ) , {
3234+ reqId,
3235+ intentType : 'tokenApproval' ,
3236+ tokenName,
3237+ feeOptions,
3238+ } ) ;
3239+
3240+ intent . should . have . property ( 'recipients' , undefined ) ;
3241+ intent . feeOptions ! . should . deepEqual ( feeOptions ) ;
3242+ intent . tokenName ! . should . equal ( tokenName ) ;
3243+ intent . intentType . should . equal ( 'tokenApproval' ) ;
3244+ } ) ;
3245+
31833246 it ( 'should populate intent with custodianTransactionId' , async function ( ) {
31843247 const mpcUtils = new ECDSAUtils . EcdsaUtils ( bitgo , bitgo . coin ( 'hteth' ) ) ;
31853248 const feeOptions = {
@@ -4965,4 +5028,99 @@ describe('V2 Wallet:', function () {
49655028 . should . be . rejectedWith ( 'invalid argument for amount - Integer greater than zero or numeric string expected' ) ;
49665029 } ) ;
49675030 } ) ;
5031+
5032+ describe ( 'Token Approval' , function ( ) {
5033+ let ethWallet ;
5034+ const tokenName = 'usdc' ;
5035+ const walletPassphrase = 'test_passphrase' ;
5036+
5037+ before ( async function ( ) {
5038+ const walletData = {
5039+ id : '598f606cd8fc24710d2ebadb1d9459bb' ,
5040+ coin : 'teth' ,
5041+ keys : [
5042+ '598f606cd8fc24710d2ebad89dce86c2' ,
5043+ '598f606cc8e43aef09fcb785221d9dd2' ,
5044+ '5935d59cf660764331bafcade1855fd7' ,
5045+ ] ,
5046+ } ;
5047+ ethWallet = new Wallet ( bitgo , bitgo . coin ( 'teth' ) , walletData ) ;
5048+ } ) ;
5049+
5050+ it ( 'should successfully approve ERC20 token' , async function ( ) {
5051+ const mockTokenApprovalBuild = {
5052+ txPrebuild : {
5053+ txHex : '0x1234567890abcdef' ,
5054+ txInfo : {
5055+ gasPrice : 20000000000 ,
5056+ gasLimit : 60000 ,
5057+ nonce : 1 ,
5058+ } ,
5059+ } ,
5060+ coin : 'teth' ,
5061+ tokenName : tokenName ,
5062+ } ;
5063+
5064+ const mockSignedTransaction = {
5065+ txHex : '0xabcdef1234567890' ,
5066+ halfSigned : {
5067+ txHex : '0xabcdef1234567890' ,
5068+ } ,
5069+ } ;
5070+
5071+ const mockSentTransaction = {
5072+ hash : '0x9876543210fedcba' ,
5073+ status : 'signed' ,
5074+ } ;
5075+
5076+ // Mock the token approval build endpoint
5077+ const buildScope = nock ( bgUrl )
5078+ . post ( `/api/v2/teth/wallet/${ ethWallet . id ( ) } /token/approval/build` )
5079+ . reply ( 200 , mockTokenApprovalBuild ) ;
5080+
5081+ // Mock getKeychainsAndValidatePassphrase
5082+ sinon . stub ( ethWallet , 'getKeychainsAndValidatePassphrase' ) . resolves ( [
5083+ {
5084+ id : '598f606cd8fc24710d2ebad89dce86c2' ,
5085+ prv : 'test_private_key' ,
5086+ } ,
5087+ ] ) ;
5088+
5089+ // Mock signTransaction
5090+ sinon . stub ( ethWallet , 'signTransaction' ) . resolves ( mockSignedTransaction ) ;
5091+
5092+ // Mock sendTransaction
5093+ sinon . stub ( ethWallet , 'sendTransaction' ) . resolves ( mockSentTransaction ) ;
5094+
5095+ const result = await ethWallet . approveErc20Token ( walletPassphrase , tokenName ) ;
5096+
5097+ result . should . equal ( mockSentTransaction ) ;
5098+ buildScope . isDone ( ) . should . be . true ( ) ;
5099+ } ) ;
5100+
5101+ it ( 'should handle token approval build failure' , async function ( ) {
5102+ const buildScope = nock ( bgUrl )
5103+ . post ( `/api/v2/teth/wallet/${ ethWallet . id ( ) } /token/approval/build` )
5104+ . reply ( 400 , { error : 'Invalid token name' } ) ;
5105+
5106+ sinon . stub ( ethWallet , 'getKeychainsAndValidatePassphrase' ) . resolves ( [
5107+ {
5108+ id : '598f606cd8fc24710d2ebad89dce86c2' ,
5109+ prv : 'test_private_key' ,
5110+ } ,
5111+ ] ) ;
5112+
5113+ await ethWallet . approveErc20Token ( walletPassphrase , 'invalid_token' ) . should . be . rejectedWith ( 'Invalid token name' ) ;
5114+
5115+ buildScope . isDone ( ) . should . be . true ( ) ;
5116+ } ) ;
5117+
5118+ it ( 'should validate required parameters for approveErc20Token' , async function ( ) {
5119+ await ethWallet . approveErc20Token ( '' , tokenName ) . should . be . rejectedWith ( ) ;
5120+ } ) ;
5121+
5122+ afterEach ( function ( ) {
5123+ sinon . restore ( ) ;
5124+ } ) ;
5125+ } ) ;
49685126} ) ;
0 commit comments