Skip to content

Commit c3a2d01

Browse files
authored
Merge pull request #8063 from BitGo/SC-5233
feat(flrp): add TxBuilder for P-chain staking
2 parents ef31d76 + c04f75f commit c3a2d01

File tree

11 files changed

+937
-9
lines changed

11 files changed

+937
-9
lines changed

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

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ export class Flrp extends BaseCoin {
111111
this.validateImportTx(explainedTx.inputs, params.txParams);
112112
}
113113
break;
114+
case TransactionType.AddPermissionlessDelegator:
115+
// Validate delegation transaction against both txParams and explainedTx
116+
this.validateDelegationTx(params.txParams, explainedTx);
117+
break;
114118
default:
115119
throw new Error('Tx type is not supported yet');
116120
}
@@ -166,6 +170,52 @@ export class Flrp extends BaseCoin {
166170
}
167171
}
168172

173+
/**
174+
* Validate AddPermissionlessDelegator transaction parameters.
175+
* Validates both expected txParams and the parsed explainedTx for consistency.
176+
*
177+
* @param {FlrpTransactionParams} txParams - Expected transaction parameters
178+
* @param {FlrpLib.TransactionExplanation} explainedTx - Parsed transaction explanation
179+
*/
180+
validateDelegationTx(txParams: FlrpTransactionParams, explainedTx: FlrpLib.TransactionExplanation): void {
181+
if (!txParams.stakingOptions) {
182+
throw new Error('Delegation transaction requires stakingOptions');
183+
}
184+
185+
const { nodeID, amount, durationSeconds, rewardAddress } = txParams.stakingOptions;
186+
187+
if (!nodeID) {
188+
throw new Error('Delegation transaction requires nodeID');
189+
}
190+
191+
if (!amount) {
192+
throw new Error('Delegation transaction requires amount');
193+
}
194+
195+
if (!durationSeconds) {
196+
throw new Error('Delegation transaction requires durationSeconds');
197+
}
198+
199+
if (!rewardAddress) {
200+
throw new Error('Delegation transaction requires rewardAddress');
201+
}
202+
203+
// Validate nodeID format using utility method
204+
if (!utils.isValidNodeID(nodeID)) {
205+
throw new Error(`Invalid nodeID format: ${nodeID}`);
206+
}
207+
208+
// Validate that the parsed transaction's output amount matches the expected staking amount
209+
// The outputAmount in explainedTx represents the total stake amount in the transaction
210+
if (explainedTx.outputAmount) {
211+
const expectedAmount = new BigNumber(amount);
212+
const actualAmount = new BigNumber(explainedTx.outputAmount);
213+
if (!expectedAmount.isEqualTo(actualAmount)) {
214+
throw new Error(`Delegation amount mismatch: expected ${amount}, transaction has ${explainedTx.outputAmount}`);
215+
}
216+
}
217+
}
218+
169219
private getBuilder(): FlrpLib.TransactionBuilderFactory {
170220
return new FlrpLib.TransactionBuilderFactory(coins.get(this.getChain()));
171221
}

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

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,37 @@ export type Tx =
7979
| evmSerial.ExportTx
8080
| evmSerial.ImportTx
8181
| pvmSerial.ExportTx
82-
| pvmSerial.ImportTx;
82+
| pvmSerial.ImportTx
83+
| pvmSerial.AddPermissionlessDelegatorTx;
8384

84-
export type SerializedTx = evmSerial.ExportTx | evmSerial.ImportTx | pvmSerial.ExportTx | pvmSerial.ImportTx;
85+
export type SerializedTx =
86+
| evmSerial.ExportTx
87+
| evmSerial.ImportTx
88+
| pvmSerial.ExportTx
89+
| pvmSerial.ImportTx
90+
| pvmSerial.AddPermissionlessDelegatorTx;
8591
export type BaseTx = pvmSerial.BaseTx;
8692
export type Output = TransferableOutput;
8793
export interface FlrpVerifyTransactionOptions extends VerifyTransactionOptions {
8894
txParams: FlrpTransactionParams;
8995
}
9096

97+
/**
98+
* Staking options for AddPermissionlessDelegator transactions
99+
*/
100+
export interface FlrpStakingOptions {
101+
nodeID: string;
102+
amount: string | number;
103+
durationSeconds: string | number;
104+
rewardAddress: string;
105+
}
106+
91107
export interface FlrpTransactionParams extends TransactionParams {
92108
type: string;
93109
locktime?: number;
94110
unspents?: string[];
95111
sourceChain?: string;
112+
stakingOptions?: FlrpStakingOptions;
96113
}
97114

98115
export interface FlrpEntry extends Entry {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ export { AtomicTransactionBuilder } from './atomicTransactionBuilder';
99
export { AtomicInCTransactionBuilder } from './atomicInCTransactionBuilder';
1010
export { ImportInCTxBuilder } from './ImportInCTxBuilder';
1111
export { ImportInPTxBuilder } from './ImportInPTxBuilder';
12+
export { PermissionlessDelegatorTxBuilder } from './permissionlessDelegatorTxBuilder';

0 commit comments

Comments
 (0)