Skip to content

Commit

Permalink
Merge pull request #3703 from BitGo/EA-656
Browse files Browse the repository at this point in the history
chore(sdk-coin-ada): parse detailed pledging information
  • Loading branch information
evanzbitgo authored Jun 30, 2023
2 parents 0da145f + abf86e2 commit dde6b7b
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 0 deletions.
96 changes: 96 additions & 0 deletions modules/sdk-coin-ada/src/lib/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,27 @@ export interface Withdrawal {
stakeAddress: string;
value: string;
}

export type StakeKeyRegistrationCert = Cert;

export type StakeKeyDelegationCert = Cert;

export interface StakePoolRegistrationCert extends Cert {
vrfKeyHash: string;
pledge: string;
cost: string;
marginNumerator: string;
marginDenominator: string;
rewardAccount: string;
poolOwners: string[];
}

export interface PledgeDetails {
stakeKeyRegsitration?: StakeKeyRegistrationCert;
stakeKeyDelegation?: StakeKeyDelegationCert;
stakePoolRegistration: StakePoolRegistrationCert;
}

/**
* The transaction data returned from the toJson() function of a transaction
*/
Expand All @@ -52,11 +73,13 @@ export interface TxData {
witnesses: Witness[];
certs: Cert[];
withdrawals: Withdrawal[];
pledgeDetails?: PledgeDetails;
}

export class Transaction extends BaseTransaction {
private _transaction: CardanoWasm.Transaction;
private _fee: string;
private _pledgeDetails?: PledgeDetails;

constructor(coinConfig: Readonly<CoinConfig>) {
super(coinConfig);
Expand Down Expand Up @@ -155,6 +178,8 @@ export class Transaction extends BaseTransaction {
}
}

result.pledgeDetails = this._pledgeDetails;

if (this._transaction.body().withdrawals()) {
const withdrawals = this._transaction.body().withdrawals() as CardanoWasm.Withdrawals;
const keys = withdrawals.keys();
Expand Down Expand Up @@ -233,6 +258,15 @@ export class Transaction extends BaseTransaction {

if (certs.some((c) => c.as_pool_registration() !== undefined)) {
this._type = TransactionType.StakingPledge;
const stakeKeyRegistration = certs.find((c) => c.as_stake_registration() !== undefined);
const stakeKeyDelegation = certs.find((c) => c.as_stake_delegation() !== undefined);
const stakePoolRegistration = certs.find((c) => c.as_pool_registration() !== undefined);

this._pledgeDetails = {
stakeKeyRegsitration: this.loadStakeKeyRegistration(stakeKeyRegistration),
stakeKeyDelegation: this.loadStakeKeyDelegation(stakeKeyDelegation),
stakePoolRegistration: this.loadStakePoolRegistration(stakePoolRegistration!),
};
} else if (certs.some((c) => c.as_stake_registration() !== undefined)) {
this._type = TransactionType.StakingActivate;
} else if (certs.some((c) => c.as_stake_deregistration() !== undefined)) {
Expand All @@ -258,6 +292,62 @@ export class Transaction extends BaseTransaction {
}
}

private loadStakeKeyRegistration(
certificate: CardanoWasm.Certificate | undefined
): StakeKeyRegistrationCert | undefined {
if (certificate === undefined) {
return undefined;
}
const stakeRegistration = certificate.as_stake_registration();
if (stakeRegistration !== undefined && stakeRegistration!.stake_credential().to_keyhash() !== undefined) {
return {
type: CertType.StakeKeyRegistration,
stakeCredentialHash: stakeRegistration!.stake_credential().to_keyhash()!.to_hex(),
};
} else {
return undefined;
}
}

private loadStakeKeyDelegation(certificate: CardanoWasm.Certificate | undefined): StakeKeyDelegationCert | undefined {
if (certificate === undefined) {
return undefined;
}
const stakeDelegation = certificate.as_stake_delegation();
if (stakeDelegation !== undefined && stakeDelegation!.stake_credential().to_keyhash() !== undefined) {
return {
type: CertType.StakeKeyDelegation,
stakeCredentialHash: stakeDelegation!.stake_credential().to_keyhash()!.to_hex(),
poolKeyHash: stakeDelegation!.pool_keyhash().to_hex(),
};
} else {
return undefined;
}
}

private loadStakePoolRegistration(certificate: CardanoWasm.Certificate): StakePoolRegistrationCert {
const poolRegistration = certificate.as_pool_registration();
const rewardAccount = poolRegistration!.pool_params().reward_account();
const networkId = rewardAccount.to_address().network_id();
const owners: string[] = [];
for (let i = 0; i < poolRegistration!.pool_params().pool_owners().len(); i++) {
const poolOwner = poolRegistration!.pool_params().pool_owners().get(i);
const ownerStakeKey = CardanoWasm.StakeCredential.from_keyhash(poolOwner);
owners.push(CardanoWasm.RewardAddress.new(networkId, ownerStakeKey).to_address().to_bech32());
}
return {
type: CertType.StakePoolRegistration,
poolKeyHash: poolRegistration!.pool_params().operator().to_hex(),
vrfKeyHash: poolRegistration!.pool_params().vrf_keyhash().to_hex(),
pledge: poolRegistration!.pool_params().pledge().to_str(),
cost: poolRegistration!.pool_params().cost().to_str(),
marginNumerator: poolRegistration!.pool_params().margin().numerator().to_str(),
marginDenominator: poolRegistration!.pool_params().margin().denominator().to_str(),
rewardAccount: rewardAccount.to_address().to_bech32(),
poolOwners: owners,
};
}

/**
* Set the transaction type.
*
Expand All @@ -279,6 +369,7 @@ export class Transaction extends BaseTransaction {
changeAmount: string;
type: string;
withdrawals: Withdrawal[];
pledgeDetails?: PledgeDetails;
} {
const txJson = this.toJson();
const displayOrder = ['id', 'outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee', 'type'];
Expand Down Expand Up @@ -307,9 +398,14 @@ export class Transaction extends BaseTransaction {
type,
certificates: txJson.certs,
withdrawals: txJson.withdrawals,
pledgeDetails: this._pledgeDetails,
};
}

getPledgeDetails(): PledgeDetails | undefined {
return this._pledgeDetails;
}

/**
* Get transaction fee
*/
Expand Down
1 change: 1 addition & 0 deletions modules/sdk-coin-ada/test/unit/ada.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ describe('ADA', function () {
type: 'Transfer',
certificates: [],
withdrawals: [],
pledgeDetails: undefined,
};

before(function () {
Expand Down
37 changes: 37 additions & 0 deletions modules/sdk-coin-ada/test/unit/stakingPledgeBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@ describe('ADA Staking Pledge Transaction Builder', async () => {
txData.certs[0].poolKeyHash!.should.equal('10324dc34187735de46f6260d94620cdcc819f7ed1f93e3fc58d06a0');
txData.withdrawals.length.should.equal(0);
txData.witnesses.length.should.equal(0);
should.exist(txData.pledgeDetails);
should.not.exist(txData.pledgeDetails!.stakeKeyRegsitration);
should.exist(txData.pledgeDetails!.stakeKeyDelegation);
should.exist(txData.pledgeDetails!.stakePoolRegistration);
should.equal(
txData.pledgeDetails!.stakeKeyDelegation!.poolKeyHash,
txData.pledgeDetails!.stakePoolRegistration!.poolKeyHash
);
txData.pledgeDetails!.stakePoolRegistration!.pledge.should.equal('100000000');
txData.pledgeDetails!.stakePoolRegistration!.cost.should.equal('500000000');
txData.pledgeDetails!.stakePoolRegistration!.marginNumerator.should.equal('3');
txData.pledgeDetails!.stakePoolRegistration!.marginDenominator.should.equal('20');
txData.pledgeDetails!.stakePoolRegistration!.rewardAccount.should.equal(
txData.pledgeDetails!.stakePoolRegistration!.poolOwners[0]
);

const fee = tx.getFee;
fee.should.equal('1000000');
Expand All @@ -50,6 +65,17 @@ describe('ADA Staking Pledge Transaction Builder', async () => {
txData.certs[0].poolKeyHash!.should.equal('10324dc34187735de46f6260d94620cdcc819f7ed1f93e3fc58d06a0');
txData.withdrawals.length.should.equal(0);
txData.witnesses.length.should.equal(0);
should.exist(txData.pledgeDetails);
should.not.exist(txData.pledgeDetails!.stakeKeyRegsitration);
should.not.exist(txData.pledgeDetails!.stakeKeyDelegation);
should.exist(txData.pledgeDetails!.stakePoolRegistration);
txData.pledgeDetails!.stakePoolRegistration!.pledge.should.equal('100000000');
txData.pledgeDetails!.stakePoolRegistration!.cost.should.equal('500000000');
txData.pledgeDetails!.stakePoolRegistration!.marginNumerator.should.equal('3');
txData.pledgeDetails!.stakePoolRegistration!.marginDenominator.should.equal('20');
txData.pledgeDetails!.stakePoolRegistration!.rewardAccount.should.equal(
txData.pledgeDetails!.stakePoolRegistration!.poolOwners[0]
);

const fee = tx.getFee;
fee.should.equal('1000000');
Expand All @@ -70,6 +96,17 @@ describe('ADA Staking Pledge Transaction Builder', async () => {
tx.signature.length.should.equal(1);
const txData = tx.toJson();
txData.witnesses.length.should.equal(1);
should.exist(txData.pledgeDetails);
should.not.exist(txData.pledgeDetails!.stakeKeyRegsitration);
should.not.exist(txData.pledgeDetails!.stakeKeyDelegation);
should.exist(txData.pledgeDetails!.stakePoolRegistration);
txData.pledgeDetails!.stakePoolRegistration!.pledge.should.equal('100000000');
txData.pledgeDetails!.stakePoolRegistration!.cost.should.equal('500000000');
txData.pledgeDetails!.stakePoolRegistration!.marginNumerator.should.equal('3');
txData.pledgeDetails!.stakePoolRegistration!.marginDenominator.should.equal('20');
txData.pledgeDetails!.stakePoolRegistration!.rewardAccount.should.equal(
txData.pledgeDetails!.stakePoolRegistration!.poolOwners[0]
);

const rebuiltTx = new Transaction(coins.get('tada'));
rebuiltTx.fromRawTransaction(tx.toBroadcastFormat());
Expand Down

0 comments on commit dde6b7b

Please sign in to comment.