feat: add decode transactions

This commit is contained in:
Kyle Fang
2022-03-27 12:21:41 +08:00
parent a9311db572
commit 88bc5f3c0e
5 changed files with 107 additions and 5 deletions

View File

@@ -25,6 +25,9 @@
"typescript": "^4.6.3",
"yargs": "^17.4.0"
},
"dependencies": {
"@stacks/stacks-blockchain-api-types": "^3.0.2"
},
"peerDependencies": {
"@stacks/transactions": "*"
}

View File

@@ -1,2 +1,3 @@
export * from "./runtime/contractBase";
export * from "./runtime/transcoders";
export * from "./runtime/decodeContractCallTransaction";

View File

@@ -61,12 +61,14 @@ export type ReturnTypeOfDescriptor<D> = D extends FunctionDescriptor
: never
: never;
export type ContractBaseType = {
[contracts: string]: {
[func: string]: FunctionDescriptor;
};
};
export function defineContract<
T extends {
[contracts: string]: {
[func: string]: FunctionDescriptor;
};
}
T extends ContractBaseType
>(contracts: T): T {
return contracts;
}

View File

@@ -0,0 +1,91 @@
import { ContractCallTransaction } from "@stacks/stacks-blockchain-api-types";
import { deserializeCV } from "@stacks/transactions";
import {
ContractBaseType,
FunctionDescriptor,
ParameterObjOfDescriptor,
ReturnTypeOfDescriptor,
} from "./contractBase";
export type ContractCallTransactionResultMap<Contracts extends ContractBaseType> = {
[C in keyof Contracts]: {
[F in keyof Contracts[C]]: {
contractName: C;
functionName: F;
args: ParameterObjOfDescriptor<Contracts[C][F]>;
result: ReturnTypeOfDescriptor<Contracts[C][F]>;
};
};
};
export type ContractCallTransactionResult<Contracts extends ContractBaseType> = {
[K in keyof ContractCallTransactionResultMap<Contracts>]: ContractCallTransactionResultMap<Contracts>[K][keyof ContractCallTransactionResultMap<Contracts>[K]];
}[keyof ContractCallTransactionResultMap<Contracts>];
export function decodeContractCallTransaction<
Contracts extends ContractBaseType
>(
contracts: Contracts,
tx: ContractCallTransaction
): ContractCallTransactionResult<Contracts> {
if (!(tx.contract_call.contract_id in contracts)) {
throw new Error(
`[decodeContractCallTransaction] unknown contract id ${tx.contract_call.contract_id}`
);
}
const contractName = tx.contract_call.contract_id as keyof Contracts;
if (!(tx.contract_call.function_name in contracts[contractName])) {
throw new Error(
`[decodeContractCallTransaction] unknown function name ${contractName}.${tx.contract_call.function_name}`
);
}
const functionName = tx.contract_call
.function_name as keyof Contracts[keyof Contracts];
return {
contractName,
functionName,
...decodeSpecifiedContractCallTransaction(
contracts,
contractName,
functionName,
tx
),
};
}
export function decodeSpecifiedContractCallTransaction<
Contracts extends ContractBaseType,
T extends keyof Contracts,
F extends keyof Contracts[T]
>(
contracts: Contracts,
contractOrType: T,
functionName: F,
tx: ContractCallTransaction
): {
args: ParameterObjOfDescriptor<Contracts[T][F]>;
result: ReturnTypeOfDescriptor<Contracts[T][F]>;
raw: ContractCallTransaction;
} {
const functionDescriptor = contracts[contractOrType][
functionName
] as any as FunctionDescriptor;
const args = functionDescriptor.input.reduce(
(acc, arg, index) => ({
...acc,
[arg.name]: arg.type.decode(
deserializeCV(tx.contract_call.function_args![index]!.hex)
),
}),
{} as Record<string, any>
);
const result = functionDescriptor.output.decode(
deserializeCV(tx.tx_result.hex)
);
return { args: args as any, result, raw: tx };
}

View File

@@ -29,6 +29,11 @@
dependencies:
"@stacks/common" "^3.3.0"
"@stacks/stacks-blockchain-api-types@^3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@stacks/stacks-blockchain-api-types/-/stacks-blockchain-api-types-3.0.2.tgz#f291f4f0cd28b26b9007debd16c688ca6e20a724"
integrity sha512-HurLltAqFVP2raQim9iQ6Gf0QH76hvfA22vHBeCf8lcU//4tw4MvFtPxl/MkspH4BqaoM+yqJ7rHpRV9TDgCCg==
"@stacks/transactions@^3.3.0":
version "3.3.0"
resolved "https://registry.yarnpkg.com/@stacks/transactions/-/transactions-3.3.0.tgz#ccc489196dc406d06271631f28f41937b96de897"