Skip to content

Commit

Permalink
Merge pull request #1248 from input-output-hk/master
Browse files Browse the repository at this point in the history
Keep master & conway-era aligned
  • Loading branch information
mirceahasegan committed May 7, 2024
2 parents 77db600 + 7c5e8d2 commit 3b039f5
Show file tree
Hide file tree
Showing 11 changed files with 336 additions and 197 deletions.
2 changes: 1 addition & 1 deletion nix/cardano-services/oci-images.nix
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ let
}
] ''
mkdir -p $out/config
cp ${self}/compose/schedules.json $out/config/schedules.json
cp ${builtins.path { path = self + "/compose/schedules.json"; }} $out/config/schedules.json;
'';
in {
cardano-services = std.lib.ops.mkStandardOCI {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ export class TypeormStakePoolProvider extends TypeormProvider implements StakePo
[
'DROP TABLE IF EXISTS tmp_fuzzy',
'CREATE TEMPORARY TABLE tmp_fuzzy (pool_id VARCHAR, score NUMERIC) WITHOUT OIDS',
`INSERT INTO tmp_fuzzy VALUES ${values}`
...(values === '' ? [] : [`INSERT INTO tmp_fuzzy VALUES ${values}`])
].join(';')
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,14 @@ describe('TypeormStakePoolProvider', () => {
});
expect(response.pageResults.map(({ metadata }) => metadata?.ticker)).toEqual(['SP11', 'SP10', 'SP1']);
});

it('returns an empty array on empty search result', async () => {
const response = await provider.queryStakePools({
filters: { text: 'no one match this search' },
pagination
});
expect(response.pageResults).toEqual([]);
});
});

describe('stake pools sort', () => {
Expand Down
10 changes: 6 additions & 4 deletions packages/core/src/Cardano/types/Governance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,14 @@ export type Voter =
| DrepScriptHashVoter
| StakePoolKeyHashVoter;

export type VotingProcedureVote = {
actionId: GovernanceActionId;
votingProcedure: VotingProcedure;
};

export type VotingProcedures = Array<{
voter: Voter;
votes: Array<{
actionId: GovernanceActionId;
votingProcedure: VotingProcedure;
}>;
votes: VotingProcedureVote[];
}>;

export type ProposalProcedure = {
Expand Down
7 changes: 5 additions & 2 deletions packages/hardware-ledger/src/LedgerKeyAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,11 @@ export class LedgerKeyAgent extends KeyAgentBase {
}
}

if (tx.collateralInputs) {
/**
* VotingProcedures: We are currently supporting only keyHash and scriptHash voter types in voting procedures.
* To sign tx with keyHash and scriptHash voter type we have to use PLUTUS_TRANSACTION signing mode
*/
if (tx.collateralInputs || tx.votingProcedures) {
return TransactionSigningMode.PLUTUS_TRANSACTION;
}

Expand Down Expand Up @@ -552,7 +556,6 @@ export class LedgerKeyAgent extends KeyAgentBase {
);

const signingMode = LedgerKeyAgent.getSigningMode(ledgerTxData);

const result = await deviceConnection.signTransaction({
signingMode,
tx: ledgerTxData
Expand Down
120 changes: 62 additions & 58 deletions packages/hardware-ledger/src/transformers/votingProcedures.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,45 @@
import * as Ledger from '@cardano-foundation/ledgerjs-hw-app-cardano';
import { Cardano } from '@cardano-sdk/core';
import {
CommitteeKeyHashVoter,
CommitteeScriptHashVoter,
DRepKeyHashVoter,
DRepScriptHashVoter,
StakePoolKeyHashVoter,
Vote,
VoteOption,
Voter,
VoterType,
VoterVotes
} from '@cardano-foundation/ledgerjs-hw-app-cardano';
import { Transform } from '@cardano-sdk/util';

/**
* Maps a Voter to a Voter from the LedgerJS public types.
*
* @param {Cardano.Voter} voter - The voter object defined in Core types.
* @returns {Voter} Corresponding Voter object for use with LedgerJS.
* @returns {Ledger.Voter} Corresponding Voter object for use with LedgerJS.
*/
export const mapVoterToLedgerVoter = (voter: Cardano.Voter): Voter => {

export const toVoter: Transform<Cardano.Voter, Ledger.Voter> = (voter) => {
switch (voter.__typename) {
case 'ccHotKeyHash':
return {
keyHashHex: voter.credential.hash,
type: VoterType.COMMITTEE_KEY_HASH
} as CommitteeKeyHashVoter;
type: Ledger.VoterType.COMMITTEE_KEY_HASH
} as Ledger.CommitteeKeyHashVoter;

case 'ccHotScriptHash':
return {
scriptHashHex: voter.credential.hash,
type: VoterType.COMMITTEE_SCRIPT_HASH
} as CommitteeScriptHashVoter;
type: Ledger.VoterType.COMMITTEE_SCRIPT_HASH
} as Ledger.CommitteeScriptHashVoter;

case 'dRepKeyHash':
return {
keyHashHex: voter.credential.hash,
type: VoterType.DREP_KEY_HASH
} as DRepKeyHashVoter;
type: Ledger.VoterType.DREP_KEY_HASH
} as Ledger.DRepKeyHashVoter;

case 'dRepScriptHash':
return {
scriptHashHex: voter.credential.hash,
type: VoterType.DREP_SCRIPT_HASH
} as DRepScriptHashVoter;
type: Ledger.VoterType.DREP_SCRIPT_HASH
} as Ledger.DRepScriptHashVoter;

case 'stakePoolKeyHash':
return {
keyHashHex: voter.credential.hash,
type: VoterType.STAKE_POOL_KEY_HASH
} as StakePoolKeyHashVoter;
type: Ledger.VoterType.STAKE_POOL_KEY_HASH
} as Ledger.StakePoolKeyHashVoter;

default:
throw new Error('Unsupported voter type');
Expand All @@ -59,56 +50,69 @@ export const mapVoterToLedgerVoter = (voter: Cardano.Voter): Voter => {
* Maps Vote to a LedgerJS VoteOption.
*
* @param {Cardano.Vote} vote - The vote integer representing a voting decision.
* @returns {VoteOption} The corresponding LedgerJS VoteOption.
* @returns {Ledger.VoteOption} The corresponding LedgerJS VoteOption.
*/
export const mapVoteOption = (vote: Cardano.Vote): VoteOption => {

export const toVoteOption: Transform<Cardano.Vote, Ledger.VoteOption> = (vote) => {
// Implement this based on how the raw data translates to VoteOption
switch (vote) {
case 0:
return VoteOption.NO;
return Ledger.VoteOption.NO;
case 1:
return VoteOption.YES;
return Ledger.VoteOption.YES;
case 2:
return VoteOption.ABSTAIN;
return Ledger.VoteOption.ABSTAIN;
default:
throw new Error('Unsupported vote type');
}
};

/**
* Maps voting procedure votes to a LedgerJS voting procedure votes.
*
* @param {Cardano.VotingProcedureVote[]} voting procedure votes from Core
* @returns {Ledger.Vote[]} The corresponding LedgerJS voting procedure votes.
*/

export const toVotes: Transform<Cardano.VotingProcedureVote[], Ledger.Vote[]> = (votes) =>
votes.map((vote) => ({
govActionId: {
govActionIndex: vote.actionId.actionIndex,
txHashHex: vote.actionId.id
},
votingProcedure: {
...(vote.votingProcedure.anchor && {
anchor: {
hashHex: vote.votingProcedure.anchor.dataHash,
url: vote.votingProcedure.anchor.url
}
}),
vote: toVoteOption(vote.votingProcedure.vote)
}
}));

/**
* Maps voting procedure from Core to LedgerJS.
*
* @param votingProcedure A single voting procedure obj from Core.
* @returns {Ledger.VoterVotes} LedgerJS-compatible voting records
*/
export const toVotingProcedure: Transform<Cardano.VotingProcedures[0], Ledger.VoterVotes> = (votingProcedure) => ({
voter: toVoter(votingProcedure.voter),
votes: toVotes(votingProcedure.votes)
});

/**
* Maps voting procedures from Core to LedgerJS.
*
* Converts a list of Core voting procedures into a format compatible with LedgerJS. This includes converting voters,
* votes, and anchoring data.
*
* @param {VotingProcedures | undefined} votingProcedures - Array of voting procedures from Core.
* @returns {VoterVotes[] | null} Array of LedgerJS-compatible voting records or null if input is undefined.
* @param {Cardano.VotingProcedures | undefined} votingProcedures - Array of voting procedures from Core.
* @returns {Ledger.VoterVotes[] | null} Array of LedgerJS-compatible voting records or null if input is undefined.
*/
export const mapVotingProcedures = (votingProcedures: Cardano.VotingProcedures | undefined): VoterVotes[] | null => {
if (!votingProcedures) {
return null;
}

return votingProcedures.map(
(procedure): VoterVotes => ({
voter: mapVoterToLedgerVoter(procedure.voter),
votes: procedure.votes.map(
(vote): Vote => ({
govActionId: {
govActionIndex: vote.actionId.actionIndex,
txHashHex: vote.actionId.id
},
votingProcedure: {
...(vote.votingProcedure.anchor && {
anchor: {
hashHex: vote.votingProcedure.anchor.dataHash,
url: vote.votingProcedure.anchor.url
}
}),
vote: mapVoteOption(vote.votingProcedure.vote)
}
})
)
})
);
};
export const mapVotingProcedures = (
votingProcedures: Cardano.VotingProcedures | undefined
): Ledger.VoterVotes[] | null =>
votingProcedures ? votingProcedures.map((votingProcedure) => toVotingProcedure(votingProcedure)) : null;
14 changes: 12 additions & 2 deletions packages/hardware-ledger/src/transformers/withdrawals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,15 @@ export const toWithdrawal: Transform<Cardano.Withdrawal, Ledger.Withdrawal, Ledg
export const mapWithdrawals = (
withdrawals: Cardano.Withdrawal[] | undefined,
context: LedgerTxTransformerContext
): Ledger.Withdrawal[] | null =>
withdrawals ? withdrawals.map((coreWithdrawal) => toWithdrawal(coreWithdrawal, context)) : null;
): Ledger.Withdrawal[] | null => {
if (!withdrawals) return null;
// Sort withdrawals by address bytes, canonically
withdrawals.sort((a, b) => {
const rewardAddress1 = Cardano.Address.fromString(a.stakeAddress)?.asReward();
const rewardAddress2 = Cardano.Address.fromString(b.stakeAddress)?.asReward();
if (!rewardAddress1 || !rewardAddress2)
throw new InvalidArgumentError('withdrawal', 'Invalid withdrawal stake address');
return rewardAddress1.toAddress().toBytes() > rewardAddress2.toAddress().toBytes() ? 1 : -1;
});
return withdrawals.map((coreWithdrawal) => toWithdrawal(coreWithdrawal, context));
};
22 changes: 22 additions & 0 deletions packages/hardware-ledger/test/testData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Base64Blob, HexBlob } from '@cardano-sdk/util';
import { Cardano, Serialization } from '@cardano-sdk/core';
import { LedgerTxTransformerContext } from '../src';
export const rewardAccount = Cardano.RewardAccount('stake_test1up7pvfq8zn4quy45r2g572290p9vf99mr9tn7r9xrgy2l2qdsf58d');
export const rewardAccount2 = Cardano.RewardAccount('stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj');
export const stakeKeyHash = Cardano.RewardAccount.toHash(rewardAccount);
export const stakeCredential = {
hash: Crypto.Hash28ByteBase16.fromEd25519KeyHashHex(stakeKeyHash),
Expand Down Expand Up @@ -458,3 +459,24 @@ export const singleVotingProcedureMultipleVotes: Cardano.VotingProcedures = [
votes
}
];

export const votingProcedureVotes = [
{
actionId: {
actionIndex: 1,
id: 'someActionId' as Cardano.TransactionId
},
votingProcedure: {
anchor: {
dataHash: 'datahash' as Crypto.Hash32ByteBase16,
url: 'http://example.com'
},
vote: Cardano.Vote.yes
}
}
];

export const constitutionalCommitteeVotingProcedure = {
voter: ccHotKeyHashVoter,
votes: votingProcedureVotes
};

0 comments on commit 3b039f5

Please sign in to comment.