Skip to content

Commit

Permalink
from @amilano: 1) fix error in definition of receiving account guard.…
Browse files Browse the repository at this point in the history
… 2) add logic to decide whether or not to include `addKeyset` in tx. 3) create helper functions
  • Loading branch information
hcote committed Dec 13, 2024
1 parent 71442d6 commit 912c5ea
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 22 deletions.
16 changes: 16 additions & 0 deletions src/pact/keyset-ref-guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ChainId, Pact } from "@kadena/client";
import { NETWORK_ID } from "../utils/constants";
interface KeysetRefGuardTransaction {
chainId: ChainId;
keysetRefGuardName: string;
}
export const buildKeysetRefGuardTransaction = ({
chainId,
keysetRefGuardName,
}: KeysetRefGuardTransaction) => {
return Pact.builder
.execution(`(keyset-ref-guard "${keysetRefGuardName}")`)
.setMeta({ chainId })
.setNetworkId(NETWORK_ID)
.createTransaction();
};
31 changes: 20 additions & 11 deletions src/pact/transfer-create.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { ChainId, IPactDecimal } from "@kadena/types";
import { Pact, ISigner, literal } from "@kadena/client";
import { Pact, ISigner } from "@kadena/client";
import { NETWORK_ID } from "../utils/constants";
import { accountGuard } from "../utils/account-guard";
import { accountProtocol } from "../utils/account-protocol";
import { checkKeysetRefExists } from "../utils/check-keyset-ref-exists";

interface TransferCreateTransaction {
to: string;
Expand All @@ -12,7 +15,7 @@ interface TransferCreateTransaction {
isSpireKeyAccount: boolean;
}

export const buildTransferCreateTransaction = ({
export const buildTransferCreateTransaction = async ({
to,
from,
amount,
Expand All @@ -29,25 +32,31 @@ export const buildTransferCreateTransaction = ({
}
: senderPubKey;

return Pact.builder
const pactBuilder = Pact.builder
.execution(
(Pact.modules as any).coin["transfer-create"](
from,
to,
literal(
`(at 'guard (coin.details
"${to}"
))`
),
accountGuard(to),
amount
)
)
.addKeyset("receiver-guard", "keys-all", receiverPubKey)
.addSigner(signer, (withCapability: any) => [
withCapability("coin.GAS"),
withCapability("coin.TRANSFER", from, to, amount),
])
.setMeta({ chainId, senderAccount: from })
.setNetworkId(NETWORK_ID)
.setNetworkId(NETWORK_ID);

if (accountProtocol(to) === 'r:') {
const keysetRefExists = await checkKeysetRefExists(to.substring(2), chainId);
if (!keysetRefExists) {
console.error(`Keyset reference guard "${to.substring(2)}" does not exist on chain ${chainId}`);
throw new Error(`Keyset reference guard "${to.substring(2)}" does not exist on chain ${chainId}`);
}
return pactBuilder.createTransaction();
}
return pactBuilder
.addKeyset("receiverKeyset", "keys-all", receiverPubKey)
.createTransaction();
};
};
41 changes: 30 additions & 11 deletions src/pact/transfer-crosschain.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { ChainId, Pact, ISigner, literal } from "@kadena/client";
import { ChainId, Pact, ISigner, literal, readKeyset } from "@kadena/client";
import { NETWORK_ID } from "../utils/constants";
import { IPactDecimal } from "@kadena/types";
import { accountGuard } from "../utils/account-guard";
import { accountProtocol } from "../utils/account-protocol";
import { checkKeysetRefExists } from "../utils/check-keyset-ref-exists";

interface TransferCrosschainTransaction {
to: string;
Expand All @@ -13,7 +16,7 @@ interface TransferCrosschainTransaction {
isSpireKeyAccount: boolean;
}

export const buildTransferCrosschainTransaction = ({
export const buildTransferCrosschainTransaction = async ({
to,
from,
amount,
Expand All @@ -23,24 +26,19 @@ export const buildTransferCrosschainTransaction = ({
receiverPubKey,
isSpireKeyAccount,
}: TransferCrosschainTransaction) => {

const signer: ISigner = isSpireKeyAccount
? {
pubKey: senderPubKey,
scheme: "WebAuthn",
}
: senderPubKey;

return Pact.builder
const pactBuilder = Pact.builder
.execution(
(Pact.modules as any).coin.defpact["transfer-crosschain"](
from,
to,
literal(
`(at 'guard (coin.details
"${to}"
))`
),
accountGuard(to),
toChainId,
amount
)
Expand All @@ -49,8 +47,29 @@ export const buildTransferCrosschainTransaction = ({
signFor("coin.GAS"),
signFor("coin.TRANSFER_XCHAIN", from, to, amount, toChainId),
])
.addKeyset("receiver-guard", "keys-all", receiverPubKey)
.setMeta({ chainId: fromChainId, senderAccount: from })
.setNetworkId(NETWORK_ID)
.setNetworkId(NETWORK_ID);

if (accountProtocol(to) === "r:") {
const keysetRefExists = await checkKeysetRefExists(
to.substring(2),
toChainId
);
if (!keysetRefExists) {
console.error(
`Keyset reference guard "${to.substring(
2
)}" does not exist on chain ${toChainId}`
);
throw new Error(
`Keyset reference guard "${to.substring(
2
)}" does not exist on chain ${toChainId}`
);
}
return pactBuilder.createTransaction();
}
return pactBuilder
.addKeyset("receiverKeyset", "keys-all", receiverPubKey)
.createTransaction();
};
15 changes: 15 additions & 0 deletions src/utils/account-guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { literal, readKeyset } from "@kadena/client";
import { checkPrincipalAccount } from "./check-principal-account";
import { accountProtocol } from "./account-protocol";

export const accountGuard = (accountName: string) => {
if (checkPrincipalAccount(accountName)) {
if (accountProtocol(accountName) === "r:") {
return literal(`(keyset-ref-guard "${accountName.substring(2)}")`);
} else {
return readKeyset("receiverKeyset");
}
} else {
return readKeyset("receiverKeyset");
}
};
8 changes: 8 additions & 0 deletions src/utils/account-protocol.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { checkPrincipalAccount } from "./check-principal-account";

export const accountProtocol = (accountName: string) => {
if (checkPrincipalAccount(accountName)) {
return accountName.substring(0, 2);
}
return null;
};
33 changes: 33 additions & 0 deletions src/utils/check-keyset-ref-exists.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ChainId } from "@kadena/types";
import { getKadenaClient } from "./client";
import { buildKeysetRefGuardTransaction } from "../pact/keyset-ref-guard";

export const checkKeysetRefExists = async (
keysetRefGuardName: string,
chainId: ChainId
) => {
const kadenaClient = getKadenaClient(chainId);
try {
const transaction = buildKeysetRefGuardTransaction({
chainId,
keysetRefGuardName,
});
const response = await kadenaClient.dirtyRead(transaction);
if (response.result.status === "failure") {
console.error(
"not able to check",
(response.result.error as any).message
);
return false;
} else {
console.log(response.result.data);
return true;
}
} catch (error) {
console.error(
`Failed to send transaction to check the keyset defined as "${keysetRefGuardName}" on chain ${chainId}`
);
console.error(error);
return false;
}
};
7 changes: 7 additions & 0 deletions src/utils/check-principal-account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const checkPrincipalAccount = (accountName: string): boolean => {
return (
accountName.startsWith("k:") ||
accountName.startsWith("r:") ||
accountName.startsWith("w:")
);
};

0 comments on commit 912c5ea

Please sign in to comment.