Skip to content

Commit 1bafc61

Browse files
feat(sdk-coin-flrp): add createPairedWallet method to Flrp
Add CreatePairedWalletParams and CreatePairedWalletResponse interfaces to iface.ts. Add createPairedWallet() method to the Flrp class that POSTs to /api/v2/flrp/wallet/:walletId/create-paired-wallet. Add unit tests covering label/no-label and error cases. Closes #8578
1 parent eb28af8 commit 1bafc61

3 files changed

Lines changed: 115 additions & 0 deletions

File tree

modules/sdk-coin-flrp/src/flrp.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import {
2222
} from '@bitgo/sdk-core';
2323
import * as FlrpLib from './lib';
2424
import {
25+
CreatePairedWalletParams,
26+
CreatePairedWalletResponse,
2527
FlrpEntry,
2628
FlrpExplainTransactionOptions,
2729
FlrpSignTransactionOptions,
@@ -436,4 +438,12 @@ export class Flrp extends BaseCoin {
436438
auditDecryptedKey(params: AuditDecryptedKeyParams): void {
437439
throw new MethodNotImplementedError();
438440
}
441+
442+
async createPairedWallet(params: CreatePairedWalletParams): Promise<CreatePairedWalletResponse> {
443+
const { walletId, label } = params;
444+
return this.bitgo
445+
.post(this.url(`/wallet/${walletId}/create-paired-wallet`))
446+
.send(label ? { label } : {})
447+
.result();
448+
}
439449
}

modules/sdk-coin-flrp/src/lib/iface.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,34 @@ export interface ExportEVMOptions {
176176
threshold: number;
177177
locktime: bigint;
178178
}
179+
180+
/**
181+
* Parameters for creating a paired FLR C-chain wallet from an FLR P-chain wallet.
182+
*/
183+
export interface CreatePairedWalletParams {
184+
/** The ID of the source FLRP (FLR P-chain) MPC wallet. */
185+
walletId: string;
186+
/** Optional label for the new FLR C-chain wallet. */
187+
label?: string;
188+
}
189+
190+
/**
191+
* Response from the create-paired-wallet endpoint.
192+
*/
193+
export interface CreatePairedWalletResponse {
194+
id: string;
195+
coin: string;
196+
label: string;
197+
keys: string[];
198+
keySignatures: Record<string, string>;
199+
m: number;
200+
n: number;
201+
type: string;
202+
multisigType: string;
203+
coinSpecific: {
204+
pairedWalletId?: string;
205+
baseAddress?: string;
206+
[key: string]: unknown;
207+
};
208+
[key: string]: unknown;
209+
}

modules/sdk-coin-flrp/test/unit/flrp.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import { HalfSignedAccountTransaction, TransactionType, MPCAlgorithm } from '@bi
1313
import { secp256k1 } from '@flarenetwork/flarejs';
1414
import { FlrpContext } from '@bitgo/public-types';
1515
import assert from 'assert';
16+
import nock from 'nock';
17+
import { common } from '@bitgo/sdk-core';
18+
import { CreatePairedWalletResponse } from '../../src/lib/iface';
1619

1720
describe('Flrp test cases', function () {
1821
const coinName = 'flrp';
@@ -960,4 +963,75 @@ describe('Flrp test cases', function () {
960963
});
961964
});
962965
});
966+
967+
describe('createPairedWallet', function () {
968+
const walletId = 'abc123def456abc123def456abc123de';
969+
970+
afterEach(function () {
971+
nock.cleanAll();
972+
});
973+
974+
it('should POST to create-paired-wallet and return new wallet', async function () {
975+
const bgUrl = common.Environments[bitgo.getEnv()].uri;
976+
const expectedResponse: CreatePairedWalletResponse = {
977+
id: 'newwalletid000000000000000000001',
978+
coin: 'tflr',
979+
label: 'My FLR C Wallet',
980+
keys: ['key1', 'key2', 'key3'],
981+
keySignatures: { backupPub: 'sig1', bitgoPub: 'sig2' },
982+
m: 2,
983+
n: 3,
984+
type: 'hot',
985+
multisigType: 'tss',
986+
coinSpecific: {
987+
pairedWalletId: walletId,
988+
baseAddress: '0x627306090abaB3A6e1400e9345bC60c78a8BEf57',
989+
},
990+
};
991+
992+
nock(bgUrl)
993+
.post(`/api/v2/tflrp/wallet/${walletId}/create-paired-wallet`, { label: 'My FLR C Wallet' })
994+
.reply(200, expectedResponse);
995+
996+
const result = await basecoin.createPairedWallet({ walletId, label: 'My FLR C Wallet' });
997+
result.should.deepEqual(expectedResponse);
998+
result.coin.should.equal('tflr');
999+
result.coinSpecific.pairedWalletId.should.equal(walletId);
1000+
});
1001+
1002+
it('should POST without body when label is not provided', async function () {
1003+
const bgUrl = common.Environments[bitgo.getEnv()].uri;
1004+
const expectedResponse: CreatePairedWalletResponse = {
1005+
id: 'newwalletid000000000000000000002',
1006+
coin: 'tflr',
1007+
label: 'FLR C wallet (from tflrp wallet abc123def456abc123def456abc123de)',
1008+
keys: ['key1', 'key2', 'key3'],
1009+
keySignatures: {},
1010+
m: 2,
1011+
n: 3,
1012+
type: 'hot',
1013+
multisigType: 'tss',
1014+
coinSpecific: { pairedWalletId: walletId },
1015+
};
1016+
1017+
nock(bgUrl)
1018+
.post(`/api/v2/tflrp/wallet/${walletId}/create-paired-wallet`, {})
1019+
.reply(200, expectedResponse);
1020+
1021+
const result = await basecoin.createPairedWallet({ walletId });
1022+
result.should.deepEqual(expectedResponse);
1023+
});
1024+
1025+
it('should propagate HTTP errors from the server', async function () {
1026+
const bgUrl = common.Environments[bitgo.getEnv()].uri;
1027+
1028+
nock(bgUrl)
1029+
.post(`/api/v2/tflrp/wallet/${walletId}/create-paired-wallet`)
1030+
.reply(400, { error: 'Source FLR P wallet is not MPC (multisigType: onchain)' });
1031+
1032+
await basecoin
1033+
.createPairedWallet({ walletId })
1034+
.should.be.rejectedWith('Source FLR P wallet is not MPC');
1035+
});
1036+
});
9631037
});

0 commit comments

Comments
 (0)