Skip to content

Commit c921902

Browse files
committed
feat: implement bitcoin onchain allocator
1 parent b3b4162 commit c921902

File tree

3 files changed

+71
-16
lines changed

3 files changed

+71
-16
lines changed

src/services/request-handler/index.ts

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import nacl from "tweetnacl";
1515
import {
1616
Address,
1717
createWalletClient,
18+
decodeAbiParameters,
1819
encodeFunctionData,
1920
Hex,
2021
http,
@@ -1056,16 +1057,61 @@ export class RequestHandlerService {
10561057
private async _signPayload(payloadParams: PayloadParams) {
10571058
const { contract } = await getOnchainAllocator();
10581059

1059-
// TODO: Once we integrate Bitcoin we might need to make multiple calls
1060-
await contract.write.signWithdrawPayloadHash([
1061-
payloadParams as any,
1062-
"0x",
1063-
// These are both the default recommended values
1064-
{
1065-
signGas: 30_000_000_000_000n,
1066-
callbackGas: 20_000_000_000_000n,
1067-
},
1068-
0,
1069-
]);
1060+
// These are both the default recommended values
1061+
const gasSettings = {
1062+
signGas: 30_000_000_000_000n,
1063+
callbackGas: 20_000_000_000_000n,
1064+
};
1065+
1066+
const chain = await getChain(payloadParams.chainId);
1067+
if (chain.vmType === "bitcoin-vm") {
1068+
const decodedData = decodeAbiParameters(
1069+
[
1070+
{
1071+
type: "tuple",
1072+
components: [
1073+
{
1074+
type: "tuple[]",
1075+
name: "utxos",
1076+
components: [
1077+
{ type: "bytes32", name: "txid" },
1078+
{ type: "uint32", name: "index" },
1079+
{ type: "uint64", name: "value" },
1080+
{ type: "bytes", name: "scriptPubKey" },
1081+
],
1082+
},
1083+
{ type: "uint64", name: "feeRate" },
1084+
],
1085+
},
1086+
],
1087+
payloadParams.data as Hex,
1088+
)[0] as {
1089+
utxos: {
1090+
txid: Hex;
1091+
index: number;
1092+
value: bigint;
1093+
scriptPubKey: Hex;
1094+
}[];
1095+
feeRate: bigint;
1096+
};
1097+
1098+
await Promise.all(
1099+
decodedData.utxos.map((_, i) =>
1100+
contract.write.signWithdrawPayloadHash([
1101+
payloadParams as any,
1102+
"0x",
1103+
gasSettings,
1104+
i,
1105+
]),
1106+
),
1107+
);
1108+
} else {
1109+
await contract.write.signWithdrawPayloadHash([
1110+
payloadParams as any,
1111+
"0x",
1112+
gasSettings,
1113+
0,
1114+
]);
1115+
}
10701116
}
10711117
}

src/utils/onchain-allocator.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ import {
1515
zeroAddress,
1616
maxUint256,
1717
} from "viem";
18-
import { privateKeyToAccount, publicKeyToAddress } from "viem/accounts";
18+
import {
19+
nonceManager,
20+
privateKeyToAccount,
21+
publicKeyToAddress,
22+
} from "viem/accounts";
1923

2024
import { KmsSigner } from "./viem-kms-signer";
2125
import { getChain } from "../common/chains";
@@ -55,9 +59,11 @@ const getPublicAndWalletClients = async () => {
5559
region: config.onchainAllocatorSenderAwsKmsKeyRegion,
5660
});
5761

58-
account = await kmsSigner.getAccount();
62+
account = await kmsSigner.getAccount({ nonceManager });
5963
} else if (config.onchainAllocatorSenderPk) {
60-
account = privateKeyToAccount(config.onchainAllocatorSenderPk as Hex);
64+
account = privateKeyToAccount(config.onchainAllocatorSenderPk as Hex, {
65+
nonceManager,
66+
});
6167
} else {
6268
throw externalError("No available onchain allocator sender");
6369
}

src/utils/viem-kms-signer/index.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { LocalAccount, toAccount } from "viem/accounts";
1+
import { LocalAccount, NonceManager, toAccount } from "viem/accounts";
22
import {
33
getEthereumAddress,
44
getPublicKey,
@@ -24,12 +24,15 @@ export class KmsSigner {
2424
this.kmsCredentials = kmsCredentials;
2525
}
2626

27-
async getAccount(): Promise<LocalAccount> {
27+
async getAccount(options?: {
28+
nonceManager?: NonceManager;
29+
}): Promise<LocalAccount> {
2830
const address = await this.getAddress();
2931
const credentials = this.kmsCredentials;
3032

3133
return toAccount({
3234
address,
35+
nonceManager: options?.nonceManager,
3336
async signMessage({ message }): Promise<`0x${string}`> {
3437
return await signDigestHex(hashMessage(message), credentials, address);
3538
},

0 commit comments

Comments
 (0)