Skip to content

Commit 4cbc0e5

Browse files
feat: flrp validators and delegator
TICKET: WIN-7084
1 parent 87694a1 commit 4cbc0e5

File tree

5 files changed

+85
-30
lines changed

5 files changed

+85
-30
lines changed

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Shared constants for Flare P-Chain (flrp) utilities and key handling.
22
// Centralizing avoids magic numbers scattered across utils and keyPair implementations.
33

4-
export const DECODED_BLOCK_ID_LENGTH = 36; // Expected decoded block identifier length
4+
export const DECODED_BLOCK_ID_LENGTH = 32; // Expected decoded block identifier length
55
export const SHORT_PUB_KEY_LENGTH = 50; // Placeholder (potential CB58 encoded form length)
66
export const COMPRESSED_PUBLIC_KEY_LENGTH = 66; // 33 bytes (compressed) hex encoded
77
export const UNCOMPRESSED_PUBLIC_KEY_LENGTH = 130; // 65 bytes (uncompressed) hex encoded
@@ -176,6 +176,15 @@ export const AMOUNT_FIELD = 'amount'; // Amount field
176176
export const TXID_FIELD = 'txid'; // Transaction ID field
177177
export const OUTPUT_IDX_FIELD = 'outputidx'; // Output index field
178178

179+
// Transaction explanation field names
180+
export const ID_FIELD = 'id'; // ID field name
181+
export const OUTPUT_AMOUNT_FIELD = 'outputAmount'; // Output amount field
182+
export const CHANGE_AMOUNT_FIELD = 'changeAmount'; // Change amount field
183+
export const OUTPUTS_FIELD = 'outputs'; // Outputs field
184+
export const CHANGE_OUTPUTS_FIELD = 'changeOutputs'; // Change outputs field
185+
export const FEE_FIELD = 'fee'; // Fee field
186+
export const TYPE_FIELD = 'type'; // Type field
187+
179188
// Signature and hash methods
180189
export const SECP256K1_SIG_TYPE = 'secp256k1'; // SECP256K1 signature type
181190
export const DER_FORMAT = 'der'; // DER format
@@ -210,6 +219,25 @@ export const REWARD_ADDRESSES_FIELD = 'rewardAddresses'; // Reward addresses fie
210219
export const SOURCE_CHAIN_FIELD = 'sourceChain'; // Source chain field
211220
export const DESTINATION_CHAIN_FIELD = 'destinationChain'; // Destination chain field
212221

222+
// Asset and network constants
223+
export const FLR_ASSET_ID = 'FLR'; // Default FLR asset ID
224+
225+
// Placeholder constants for development
226+
export const FLARE_TX_HEX_PLACEHOLDER = 'flare-tx-hex-placeholder'; // Transaction hex placeholder
227+
export const FLARE_SIGNABLE_PAYLOAD = 'flare-signable-payload'; // Signable payload placeholder
228+
export const FLARE_TRANSACTION_ID_PLACEHOLDER = 'flare-transaction-id-placeholder'; // Transaction ID placeholder
229+
export const PLACEHOLDER_NODE_ID = 'placeholder-node-id'; // Node ID placeholder
230+
231+
// Chain identifiers (short forms)
232+
export const P_CHAIN_SHORT = 'P'; // P-chain short name
233+
export const X_CHAIN_SHORT = 'X'; // X-chain short name
234+
235+
// Valid source chains for imports
236+
export const VALID_IMPORT_SOURCE_CHAINS = [P_CHAIN_SHORT, P_CHAIN_FULL, X_CHAIN_SHORT, X_CHAIN_FULL]; // Valid source chains for C-chain imports
237+
238+
// Valid P-chain import types
239+
export const VALID_P_CHAIN_IMPORT_TYPES = [PLATFORM_VM_IMPORT_TX, IMPORT_TX_TYPE, IMPORT_TYPE, P_CHAIN_IMPORT_TYPE]; // Valid P-chain import types
240+
213241
// Error messages for transactionBuilder
214242
export const ERROR_NETWORK_ID_MISMATCH = 'Network ID mismatch'; // Network ID validation error
215243
export const ERROR_BLOCKCHAIN_ID_MISMATCH_BUILDER = 'Blockchain ID mismatch'; // Blockchain ID validation error

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

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ import {
2828
ERROR_FAILED_INITIALIZE_BUILDER,
2929
OBJECT_TYPE_STRING,
3030
HEX_ENCODING,
31+
VALID_IMPORT_SOURCE_CHAINS,
32+
P_CHAIN_SHORT,
33+
UTF8_ENCODING,
34+
IMPORT_C_TYPE,
35+
TRANSFERABLE_INPUT_TYPE,
36+
CREDENTIAL_TYPE,
3137
} from './constants';
3238

3339
/**
@@ -237,7 +243,7 @@ export class ImportInCTxBuilder extends AtomicInCTransactionBuilder {
237243
}));
238244

239245
// Get source chain ID (typically P-chain for C-chain imports)
240-
const sourceChainId = this._externalChainId ? this._externalChainId.toString('hex') : 'P';
246+
const sourceChainId = this._externalChainId ? this._externalChainId.toString(HEX_ENCODING) : P_CHAIN_SHORT;
241247

242248
// Calculate fee
243249
const fee = BigInt(this.transaction._fee.fee || DEFAULT_EVM_GAS_FEE); // EVM-style gas fee
@@ -271,7 +277,7 @@ export class ImportInCTxBuilder extends AtomicInCTransactionBuilder {
271277
},
272278
],
273279
fee,
274-
type: 'import-c',
280+
type: IMPORT_C_TYPE,
275281
fromAddresses: fromAddresses.map((addr) => addr.toString('hex')),
276282
toAddress: Buffer.from(toAddress).toString('hex'),
277283
// Add FlareJS-specific metadata for future integration
@@ -336,7 +342,7 @@ export class ImportInCTxBuilder extends AtomicInCTransactionBuilder {
336342

337343
// FlareJS compatibility markers
338344
_flareJSReady: true,
339-
_type: 'TransferableInput',
345+
_type: TRANSFERABLE_INPUT_TYPE,
340346

341347
// Methods for FlareJS compatibility
342348
getAmount: () => BigInt(amount.toString()),
@@ -355,7 +361,7 @@ export class ImportInCTxBuilder extends AtomicInCTransactionBuilder {
355361

356362
// FlareJS compatibility markers
357363
_flareJSReady: true,
358-
_type: 'Credential',
364+
_type: CREDENTIAL_TYPE,
359365

360366
// Methods for FlareJS compatibility
361367
addSignature: (signature: Buffer) => enhancedCredential.signatures.push(signature),
@@ -433,13 +439,13 @@ export class ImportInCTxBuilder extends AtomicInCTransactionBuilder {
433439
}
434440

435441
// Valid source chains for C-chain imports in Flare network
436-
const validSourceChains = ['P', 'P-chain', 'X', 'X-chain'];
442+
const validSourceChains = VALID_IMPORT_SOURCE_CHAINS;
437443
const chainIdNormalized = chainId.replace('-chain', '').toUpperCase();
438444

439445
// Check if it's a predefined chain identifier
440446
if (validSourceChains.some((chain) => chain.replace('-chain', '').toUpperCase() === chainIdNormalized)) {
441447
// Store normalized chain ID (e.g., 'P' for P-chain)
442-
this._externalChainId = Buffer.from(chainIdNormalized, 'utf8');
448+
this._externalChainId = Buffer.from(chainIdNormalized, UTF8_ENCODING);
443449
return this;
444450
}
445451

@@ -459,7 +465,7 @@ export class ImportInCTxBuilder extends AtomicInCTransactionBuilder {
459465
try {
460466
this._externalChainId = Buffer.from(chainId, 'hex');
461467
} catch (error) {
462-
this._externalChainId = Buffer.from(chainId, 'utf8');
468+
this._externalChainId = Buffer.from(chainId, UTF8_ENCODING);
463469
}
464470

465471
return this;

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

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ import {
1818
OBJECT_TYPE_STRING,
1919
STRING_TYPE,
2020
NUMBER_TYPE,
21+
VALID_P_CHAIN_IMPORT_TYPES,
22+
EXPORT_TYPE,
23+
SEND_TYPE,
24+
IMPORT_TYPE,
25+
P_CHAIN_FULL,
26+
C_CHAIN_FULL,
27+
UTF8_ENCODING,
2128
} from './constants';
2229

2330
/**
@@ -158,15 +165,15 @@ export class ImportInPTxBuilder extends AtomicTransactionBuilder {
158165
}
159166

160167
// Check for P-chain import transaction type markers
161-
const validTypes = ['PlatformVM.ImportTx', 'ImportTx', 'import', 'P-chain-import'];
168+
const validTypes = VALID_P_CHAIN_IMPORT_TYPES;
162169

163170
// Primary type verification
164171
if (tx.type && typeof tx.type === STRING_TYPE) {
165172
if (validTypes.includes(tx.type as string)) {
166173
return true;
167174
}
168175
// If type is specified but not valid, return false (like 'export')
169-
if (tx.type === 'export' || tx.type === 'send') {
176+
if (tx.type === EXPORT_TYPE || tx.type === SEND_TYPE) {
170177
return false;
171178
}
172179
}
@@ -185,8 +192,8 @@ export class ImportInPTxBuilder extends AtomicTransactionBuilder {
185192
// FlareJS-specific markers
186193
const hasFlareJSMarkers =
187194
tx._flareJSReady === true ||
188-
tx._txType === 'import' ||
189-
tx._chainType === 'P-chain' ||
195+
tx._txType === IMPORT_TYPE ||
196+
tx._chainType === P_CHAIN_FULL ||
190197
tx._pvmCompatible === true;
191198

192199
// Enhanced validation for FlareJS compatibility
@@ -276,7 +283,7 @@ export class ImportInPTxBuilder extends AtomicTransactionBuilder {
276283
threshold: this.transaction._threshold,
277284
locktime: this.transaction._locktime,
278285
// FlareJS import output markers
279-
_destinationChain: 'P-chain',
286+
_destinationChain: P_CHAIN_FULL,
280287
_flareJSReady: true,
281288
},
282289
],
@@ -358,8 +365,8 @@ export class ImportInPTxBuilder extends AtomicTransactionBuilder {
358365
_pvmCompatible: true,
359366
},
360367
// Enhanced metadata for FlareJS compatibility
361-
_sourceChain: 'C-chain',
362-
_destinationChain: 'P-chain',
368+
_sourceChain: C_CHAIN_FULL,
369+
_destinationChain: P_CHAIN_FULL,
363370
};
364371

365372
// Store the input (type assertion for compatibility)
@@ -461,11 +468,11 @@ export class ImportInPTxBuilder extends AtomicTransactionBuilder {
461468
chainBuffer = Buffer.from(chainId, HEX_ENCODING);
462469
} else {
463470
// For all other formats, store as UTF-8
464-
chainBuffer = Buffer.from(chainId, 'utf8');
471+
chainBuffer = Buffer.from(chainId, UTF8_ENCODING);
465472
}
466473
} catch (error) {
467474
// Fallback to UTF-8 if hex parsing fails
468-
chainBuffer = Buffer.from(chainId, 'utf8');
475+
chainBuffer = Buffer.from(chainId, UTF8_ENCODING);
469476
}
470477

471478
this._externalChainId = chainBuffer;

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { AtomicTransactionBuilder } from './atomicTransactionBuilder';
44
import { Tx } from './iface';
55
import { TransactionWithExtensions } from './types';
66
import {
7+
ADD_PERMISSIONLESS_VALIDATOR_TYPE,
78
BLS_PUBLIC_KEY_COMPRESSED_LENGTH,
89
BLS_PUBLIC_KEY_UNCOMPRESSED_LENGTH,
910
BLS_SIGNATURE_LENGTH,
@@ -258,7 +259,7 @@ export class PermissionlessValidatorTxBuilder extends AtomicTransactionBuilder {
258259
// TODO: Implement actual FlareJS PVM API call when available
259260
// For now, create a placeholder transaction structure
260261
const validatorTx = {
261-
type: 'addPermissionlessValidator',
262+
type: ADD_PERMISSIONLESS_VALIDATOR_TYPE,
262263
nodeID: this._nodeID,
263264
blsPublicKey: this._blsPublicKey,
264265
blsSignature: this._blsSignature,

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

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,19 @@ import {
2121
} from './iface';
2222
import { KeyPair } from './keyPair';
2323
import utils from './utils';
24+
import {
25+
FLR_ASSET_ID,
26+
FLARE_TX_HEX_PLACEHOLDER,
27+
FLARE_SIGNABLE_PAYLOAD,
28+
FLARE_TRANSACTION_ID_PLACEHOLDER,
29+
PLACEHOLDER_NODE_ID,
30+
HEX_ENCODING,
31+
MEMO_FIELD,
32+
DISPLAY_ORDER_BASE,
33+
REWARD_ADDRESSES_FIELD,
34+
SOURCE_CHAIN_FIELD,
35+
DESTINATION_CHAIN_FIELD,
36+
} from './constants';
2437

2538
/**
2639
* Flare P-chain transaction implementation using FlareJS
@@ -51,7 +64,7 @@ export class Transaction extends BaseTransaction {
5164
constructor(coinConfig: Readonly<CoinConfig>) {
5265
super(coinConfig);
5366
this._network = coinConfig.network as FlareNetwork;
54-
this._assetId = 'FLR'; // Default FLR asset
67+
this._assetId = FLR_ASSET_ID; // Default FLR asset
5568
this._blockchainID = this._network.blockchainID || '';
5669
this._networkID = this._network.networkID || 0;
5770
}
@@ -158,7 +171,7 @@ export class Transaction extends BaseTransaction {
158171
}
159172

160173
toHexString(byteArray: Uint8Array): string {
161-
return Buffer.from(byteArray).toString('hex');
174+
return Buffer.from(byteArray).toString(HEX_ENCODING);
162175
}
163176

164177
/** @inheritdoc */
@@ -169,7 +182,7 @@ export class Transaction extends BaseTransaction {
169182

170183
// TODO: Implement FlareJS transaction serialization
171184
// For now, return placeholder
172-
return 'flare-tx-hex-placeholder';
185+
return FLARE_TX_HEX_PLACEHOLDER;
173186
}
174187

175188
toJson(): TxData {
@@ -228,7 +241,7 @@ export class Transaction extends BaseTransaction {
228241

229242
// TODO: Implement FlareJS signable payload extraction
230243
// For now, return placeholder
231-
return Buffer.from('flare-signable-payload');
244+
return Buffer.from(FLARE_SIGNABLE_PAYLOAD);
232245
}
233246

234247
get id(): string {
@@ -238,7 +251,7 @@ export class Transaction extends BaseTransaction {
238251

239252
// TODO: Implement FlareJS transaction ID generation
240253
// For now, return placeholder
241-
return 'flare-transaction-id-placeholder';
254+
return FLARE_TRANSACTION_ID_PLACEHOLDER;
242255
}
243256

244257
get fromAddresses(): string[] {
@@ -271,7 +284,7 @@ export class Transaction extends BaseTransaction {
271284
// TODO: Extract validator outputs from FlareJS transaction
272285
return [
273286
{
274-
address: this._nodeID || 'placeholder-node-id',
287+
address: this._nodeID || PLACEHOLDER_NODE_ID,
275288
value: this._stakeAmount?.toString() || '0',
276289
},
277290
];
@@ -280,7 +293,7 @@ export class Transaction extends BaseTransaction {
280293
// TODO: Extract delegator outputs from FlareJS transaction
281294
return [
282295
{
283-
address: this._nodeID || 'placeholder-node-id',
296+
address: this._nodeID || PLACEHOLDER_NODE_ID,
284297
value: this._stakeAmount?.toString() || '0',
285298
},
286299
];
@@ -318,7 +331,7 @@ export class Transaction extends BaseTransaction {
318331
// TODO: Implement FlareJS signature creation
319332
// This should use FlareJS signing utilities
320333
const signval = utils.createSignature(this._network, this.signablePayload, prv);
321-
return signval.toString('hex');
334+
return signval.toString(HEX_ENCODING);
322335
}
323336

324337
/**
@@ -331,11 +344,11 @@ export class Transaction extends BaseTransaction {
331344
/** @inheritdoc */
332345
explainTransaction(): TransactionExplanation {
333346
const txJson = this.toJson();
334-
const displayOrder = ['id', 'inputs', 'outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee', 'type'];
347+
const displayOrder = [...DISPLAY_ORDER_BASE];
335348

336349
// Add memo to display order if present
337350
if (this.hasMemo()) {
338-
displayOrder.push('memo');
351+
displayOrder.push(MEMO_FIELD);
339352
}
340353

341354
// Calculate total output amount
@@ -362,12 +375,12 @@ export class Transaction extends BaseTransaction {
362375

363376
if (stakingTypes.includes(txJson.type)) {
364377
rewardAddresses = this.rewardAddresses;
365-
displayOrder.splice(6, 0, 'rewardAddresses');
378+
displayOrder.splice(6, 0, REWARD_ADDRESSES_FIELD);
366379
}
367380

368381
// Add cross-chain information for export/import
369382
if (this.isTransactionForCChain) {
370-
displayOrder.push('sourceChain', 'destinationChain');
383+
displayOrder.push(SOURCE_CHAIN_FIELD, DESTINATION_CHAIN_FIELD);
371384
}
372385

373386
const explanation: TransactionExplanation & { memo?: string } = {

0 commit comments

Comments
 (0)