@wormhole-foundation/sdk-definitions 0.1.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/__tests__/connectVAA.ts +21 -0
- package/__tests__/governanceVaa.ts +139 -0
- package/__tests__/relayerVaa.ts +24 -0
- package/__tests__/transferVaa.ts +28 -0
- package/package.json +20 -0
- package/src/address.ts +105 -0
- package/src/attestation.ts +42 -0
- package/src/chain.ts +105 -0
- package/src/contracts.ts +24 -0
- package/src/index.ts +25 -0
- package/src/layout-items/amount.ts +6 -0
- package/src/layout-items/chain.ts +57 -0
- package/src/layout-items/guardianSet.ts +6 -0
- package/src/layout-items/index.ts +7 -0
- package/src/layout-items/payloadId.ts +10 -0
- package/src/layout-items/sequence.ts +6 -0
- package/src/layout-items/signature.ts +27 -0
- package/src/layout-items/universalAddress.ts +14 -0
- package/src/payloads/connect.ts +52 -0
- package/src/payloads/governance.ts +219 -0
- package/src/payloads/relayer.ts +101 -0
- package/src/payloads/tokenBridge.ts +93 -0
- package/src/platform.ts +57 -0
- package/src/protocols/cctp.ts +47 -0
- package/src/protocols/core.ts +10 -0
- package/src/protocols/tokenBridge.ts +70 -0
- package/src/relayer.ts +50 -0
- package/src/rpc.ts +16 -0
- package/src/signature.ts +26 -0
- package/src/testing/README.md +4 -0
- package/src/testing/index.ts +2 -0
- package/src/testing/mocks/api.ts +9 -0
- package/src/testing/mocks/chain.ts +18 -0
- package/src/testing/mocks/contracts.ts +57 -0
- package/src/testing/mocks/index.ts +5 -0
- package/src/testing/mocks/platform.ts +146 -0
- package/src/testing/mocks/rpc.ts +12 -0
- package/src/testing/mocks/tokenBridge.ts +68 -0
- package/src/testing/utils/address.ts +65 -0
- package/src/testing/utils/index.ts +2 -0
- package/src/testing/utils/vaa.ts +13 -0
- package/src/types.ts +73 -0
- package/src/universalAddress.ts +57 -0
- package/src/unsignedTransaction.ts +12 -0
- package/src/utils.ts +4 -0
- package/src/vaa.ts +236 -0
- package/tsconfig.cjs.json +8 -0
- package/tsconfig.esm.json +8 -0
- package/typedoc.json +4 -0
package/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import "../src/payloads/connect";
|
|
2
|
+
import { connectPayloads } from "../src/payloads/connect";
|
|
3
|
+
import { VAA, deserialize, deserializePayload } from "../src/vaa";
|
|
4
|
+
|
|
5
|
+
const cases = [
|
|
6
|
+
"AQAAAAABANyb1oS4sD9gIp0m+dKOYmrEaxx3OeWWtUbim+6oL7VnX/zUXa/di9lA0SSDRZ3DCWoqgDC4pjPoMNUNLn1P3EcAZJjzeAAAAAAAAgAAAAAAAAAAAAAAAAppFGcWs6IWIih++hYHQkxmMGmkAAAAAAAAAHDIAQAAAAAAAAAAAAAAAAeGXG6HufcCVTd+AkrOZjDB6qN/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6EgAAAAAAAAAAAwAAAAAAA5CKAAAAAAAAAAAAAAAAF9of9ThtBExj8AdHtbitHjgGRI0AAAAAAAAAAAAAAAC/aD1UHhEyBBjKeOwTMJk45sWSLwBhAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYagAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAInU4Tn/aAHroyfjAatH6hXg4Srg==",
|
|
7
|
+
];
|
|
8
|
+
|
|
9
|
+
describe("Circle Transfer VAA tests", function () {
|
|
10
|
+
it("should correctly deserialize and reserialize a Circle Transfer Relay VAA", function () {
|
|
11
|
+
for (const testCase of cases) {
|
|
12
|
+
const vaaBytes = Buffer.from(testCase, "base64");
|
|
13
|
+
|
|
14
|
+
const parsed = deserialize("Uint8Array", new Uint8Array(vaaBytes));
|
|
15
|
+
|
|
16
|
+
const x = deserializePayload("CircleTransferRelay", parsed.payload);
|
|
17
|
+
expect(x).toBeTruthy();
|
|
18
|
+
// ...
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { describe, expect, it } from "@jest/globals";
|
|
2
|
+
|
|
3
|
+
import { hexByteStringToUint8Array } from "@wormhole-foundation/sdk-base";
|
|
4
|
+
import { UniversalAddress } from "../src/universalAddress";
|
|
5
|
+
import { create, deserialize, serialize } from "../src/vaa";
|
|
6
|
+
import "../src/payloads/governance";
|
|
7
|
+
|
|
8
|
+
//monkey-patch to allow stringifying BigInts
|
|
9
|
+
(BigInt.prototype as any).toJSON = function () {
|
|
10
|
+
return this.toString();
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
//from here: https://etherscan.io/tx/0xfe57d65421ddd689a660a7906c685954fa5c1102716452cbc8acada0214e4522
|
|
14
|
+
//decode via https://vaa.dev
|
|
15
|
+
const guardianSetUpgrade =
|
|
16
|
+
"0x" +
|
|
17
|
+
/*version*/ "01" +
|
|
18
|
+
/*guardianSet*/ "00000002" +
|
|
19
|
+
/*signature count*/ "0d" +
|
|
20
|
+
/*guardian*/ "00" +
|
|
21
|
+
/*r*/ "ce45474d9e1b1e7790a2d210871e195db53a70ffd6f237cfe70e2686a32859ac" +
|
|
22
|
+
/*s*/ "43c84a332267a8ef66f59719cf91cc8df0101fd7c36aa1878d5139241660edc0" +
|
|
23
|
+
/*v*/ "01" +
|
|
24
|
+
/*guardian*/ "03" +
|
|
25
|
+
/*r*/ "75cc906156ae530786661c0cd9aef444747bc3d8d5aa84cac6a6d2933d4e1a03" +
|
|
26
|
+
/*s*/ "1cffa30383d4af8131e929d9f203f460b07309a647d6cd32ab1cc7724089392c" +
|
|
27
|
+
/*v*/ "00" +
|
|
28
|
+
/*guardian*/ "04" +
|
|
29
|
+
/*r*/ "52305156cfc90343128f97e499311b5cae174f488ff22fbc09591991a0a73d8e" +
|
|
30
|
+
/*s*/ "6af3afb8a5968441d3ab8437836407481739e9850ad5c95e6acfcc871e951bc3" +
|
|
31
|
+
/*v*/ "01" +
|
|
32
|
+
/*guardian*/ "05" +
|
|
33
|
+
/*r*/ "a7956eefc23e7c945a1966d5ddbe9e4be376c2f54e45e3d5da88c2f8692510c7" +
|
|
34
|
+
/*s*/ "429b1ea860ae94d929bd97e84923a18187e777aa3db419813a80deb84cc8d22b" +
|
|
35
|
+
/*v*/ "00" +
|
|
36
|
+
/*guardian*/ "06" +
|
|
37
|
+
/*r*/ "1b2a4f3d2666608e0aa96737689e3ba5793810ff3a52ff28ad57d8efb2096773" +
|
|
38
|
+
/*s*/ "5dc5537a2e43ef10f583d144c12a1606542c207f5b79af08c38656d3ac407133" +
|
|
39
|
+
/*v*/ "01" +
|
|
40
|
+
/*guardian*/ "08" +
|
|
41
|
+
/*r*/ "6b62c8e130af3411b3c0d91b5b50dcb01ed5f293963f901fc36e7b0e50114dce" +
|
|
42
|
+
/*s*/ "203373b32eb45971cef8288e5d928d0ed51cd86e2a3006b0af6a65c396c00908" +
|
|
43
|
+
/*v*/ "00" +
|
|
44
|
+
/*guardian*/ "09" +
|
|
45
|
+
/*r*/ "e93ab4d2c8228901a5f4525934000b2c26d1dc679a05e47fdf0ff3231d98fbc2" +
|
|
46
|
+
/*s*/ "07103159ff4116df2832eea69b38275283434e6cd4a4af04d25fa7a82990b707" +
|
|
47
|
+
/*v*/ "01" +
|
|
48
|
+
/*guardian*/ "0a" +
|
|
49
|
+
/*r*/ "a643f4cf615dfff06ffd65830f7f6cf6512dabc3690d5d9e210fdc712842dc27" +
|
|
50
|
+
/*s*/ "08b8b2c22e224c99280cd25e5e8bfb40e3d1c55b8c41774e287c1e2c352aecfc" +
|
|
51
|
+
/*v*/ "01" +
|
|
52
|
+
/*guardian*/ "0b" +
|
|
53
|
+
/*r*/ "89c1e85faa20a30601964ccc6a79c0ae53cfd26fb10863db37783428cd91390a" +
|
|
54
|
+
/*s*/ "163346558239db3cd9d420cfe423a0df84c84399790e2e308011b4b63e6b8015" +
|
|
55
|
+
/*v*/ "01" +
|
|
56
|
+
/*guardian*/ "0c" +
|
|
57
|
+
/*r*/ "a31dcb564ac81a053a268d8090e72097f94f366711d0c5d13815af1ec7d47e66" +
|
|
58
|
+
/*s*/ "2e2d1bde22678113d15963da100b668ba26c0c325970d07114b83c5698f46097" +
|
|
59
|
+
/*v*/ "01" +
|
|
60
|
+
/*guardian*/ "0d" +
|
|
61
|
+
/*r*/ "c9fda39c0d592d9ed92cd22b5425cc6b37430e236f02d0d1f8a2ef45a00bde26" +
|
|
62
|
+
/*s*/ "223c0a6eb363c8b25fd3bf57234a1d9364976cefb8360e755a267cbbb674b395" +
|
|
63
|
+
/*v*/ "01" +
|
|
64
|
+
/*guardian*/ "10" +
|
|
65
|
+
/*r*/ "8db01e444ab1003dd8b6c96f8eb77958b40ba7a85fefecf32ad00b7a47c0ae75" +
|
|
66
|
+
/*s*/ "24216262495977e09c0989dd50f280c21453d3756843608eacd17f4fdfe47600" +
|
|
67
|
+
/*v*/ "00" +
|
|
68
|
+
/*guardian*/ "12" +
|
|
69
|
+
/*r*/ "61025228ef5af837cb060bcd986fcfa84ccef75b3fa100468cfd24e7fadf9916" +
|
|
70
|
+
/*s*/ "3938f3b841a33496c2706d0208faab088bd155b2e20fd74c625bb1cc8c43677a" +
|
|
71
|
+
/*v*/ "01" +
|
|
72
|
+
/*timestamp*/ "63c53c40" +
|
|
73
|
+
/*nonce*/ "9e0c5dfa" +
|
|
74
|
+
/*emitterChain*/ "0001" +
|
|
75
|
+
/*emitterAddress*/ "0000000000000000000000000000000000000000000000000000000000000004" +
|
|
76
|
+
/*seqeuence*/ "6c5a054d7833d1e4" +
|
|
77
|
+
/*consistencyLevel*/ "20" +
|
|
78
|
+
/*module*/ "00000000000000000000000000000000000000000000000000000000436f7265" +
|
|
79
|
+
/*action*/ "02" +
|
|
80
|
+
/*chain*/ "0000" +
|
|
81
|
+
/*guardianSet*/ "00000003" +
|
|
82
|
+
/*guardians*/ "13" +
|
|
83
|
+
/*guardian*/ "58cc3ae5c097b213ce3c81979e1b9f9570746aa5" +
|
|
84
|
+
/*guardian*/ "ff6cb952589bde862c25ef4392132fb9d4a42157" +
|
|
85
|
+
/*guardian*/ "114de8460193bdf3a2fcf81f86a09765f4762fd1" +
|
|
86
|
+
/*guardian*/ "107a0086b32d7a0977926a205131d8731d39cbeb" +
|
|
87
|
+
/*guardian*/ "8c82b2fd82faed2711d59af0f2499d16e726f6b2" +
|
|
88
|
+
/*guardian*/ "11b39756c042441be6d8650b69b54ebe715e2343" +
|
|
89
|
+
/*guardian*/ "54ce5b4d348fb74b958e8966e2ec3dbd4958a7cd" +
|
|
90
|
+
/*guardian*/ "15e7caf07c4e3dc8e7c469f92c8cd88fb8005a20" +
|
|
91
|
+
/*guardian*/ "74a3bf913953d695260d88bc1aa25a4eee363ef0" +
|
|
92
|
+
/*guardian*/ "000ac0076727b35fbea2dac28fee5ccb0fea768e" +
|
|
93
|
+
/*guardian*/ "af45ced136b9d9e24903464ae889f5c8a723fc14" +
|
|
94
|
+
/*guardian*/ "f93124b7c738843cbb89e864c862c38cddcccf95" +
|
|
95
|
+
/*guardian*/ "d2cc37a4dc036a8d232b48f62cdd4731412f4890" +
|
|
96
|
+
/*guardian*/ "da798f6896a3331f64b48c12d1d57fd9cbe70811" +
|
|
97
|
+
/*guardian*/ "71aa1be1d36cafe3867910f99c09e347899c19c3" +
|
|
98
|
+
/*guardian*/ "8192b6e7387ccd768277c17dab1b7a5027c0b3cf" +
|
|
99
|
+
/*guardian*/ "178e21ad2e77ae06711549cfbb1f9c7a9d8096e8" +
|
|
100
|
+
/*guardian*/ "5e1487f35515d02a92753504a8d75471b9f49edb" +
|
|
101
|
+
/*guardian*/ "6fbebc898f403e4773e95feb15e80c9a99c8348d";
|
|
102
|
+
|
|
103
|
+
describe("Governance VAA tests", function () {
|
|
104
|
+
it("should create an empty VAA from an object with omitted fixed values", function () {
|
|
105
|
+
const vaa = create("CoreBridgeUpgradeContract", {
|
|
106
|
+
guardianSet: 0,
|
|
107
|
+
signatures: [],
|
|
108
|
+
nonce: 0,
|
|
109
|
+
timestamp: 0,
|
|
110
|
+
sequence: 0n,
|
|
111
|
+
emitterChain: "Solana",
|
|
112
|
+
emitterAddress: new UniversalAddress(new Uint8Array(32)),
|
|
113
|
+
consistencyLevel: 0,
|
|
114
|
+
payload: {
|
|
115
|
+
chain: "Ethereum",
|
|
116
|
+
//@ts-ignore
|
|
117
|
+
newContract: new UniversalAddress(new Uint8Array(32)),
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
expect(vaa.payload.protocol).toEqual("CoreBridge");
|
|
121
|
+
expect(vaa.payload.action).toEqual("UpgradeContract");
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("should correctly deserialize and reserialize a guardian set upgrade VAA", function () {
|
|
125
|
+
const vaa = deserialize("CoreBridgeGuardianSetUpgrade", guardianSetUpgrade);
|
|
126
|
+
expect(vaa.payloadLiteral).toBe("CoreBridgeGuardianSetUpgrade");
|
|
127
|
+
expect(vaa.guardianSet).toBe(2);
|
|
128
|
+
expect(vaa.signatures.length).toBe(13);
|
|
129
|
+
expect(vaa.nonce).toBe(2651610618);
|
|
130
|
+
expect(vaa.emitterChain).toBe("Solana");
|
|
131
|
+
expect(vaa.payload.protocol).toBe("CoreBridge");
|
|
132
|
+
expect(vaa.payload.action).toBe("GuardianSetUpgrade");
|
|
133
|
+
expect(vaa.payload.guardianSet).toBe(3);
|
|
134
|
+
expect(vaa.payload.guardians.length).toBe(19);
|
|
135
|
+
|
|
136
|
+
const encoded = serialize(vaa);
|
|
137
|
+
expect(encoded).toEqual(hexByteStringToUint8Array(guardianSetUpgrade));
|
|
138
|
+
});
|
|
139
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { describe, expect, it } from "@jest/globals";
|
|
2
|
+
|
|
3
|
+
import { hexByteStringToUint8Array } from "@wormhole-foundation/sdk-base";
|
|
4
|
+
import { serializePayload, deserializePayload } from "../src/vaa";
|
|
5
|
+
import "../src/payloads/relayer";
|
|
6
|
+
|
|
7
|
+
//monkey-patch to allow stringifying BigInts
|
|
8
|
+
(BigInt.prototype as any).toJSON = function () {
|
|
9
|
+
return this.toString();
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
//log taken from here: https://moonbeam.moonscan.io/tx/0x6a2c36673e8cbbef29cc3bad4eabfb8edb0851c0d27defba300f80561ccecec6
|
|
13
|
+
const original =
|
|
14
|
+
"0x01000500000000000000000000000046AF49E93E92ACE9CB04545C6548E3F12BE61FD7000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000C746573746772656574696E67000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C350000000000000000000000000000000000000000000000000000000308FD36EDB00050000000000000000000000007A0A53847776F7E94CC35742971ACB2217B0DB810000000000000000000000007A0A53847776F7E94CC35742971ACB2217B0DB810000000000000000000000007A0A53847776F7E94CC35742971ACB2217B0DB8100000000000000000000000046AF49E93E92ACE9CB04545C6548E3F12BE61FD700";
|
|
15
|
+
|
|
16
|
+
describe("Relayer VAA tests", function () {
|
|
17
|
+
it("should correctly deserialize and reserialize a relayer VAA", function () {
|
|
18
|
+
const payload = deserializePayload("DeliveryInstruction", original);
|
|
19
|
+
expect(payload.target.chain).toBe("Polygon");
|
|
20
|
+
expect(payload.refund.chain).toBe("Polygon");
|
|
21
|
+
const encoded = serializePayload("DeliveryInstruction", payload);
|
|
22
|
+
expect(encoded).toEqual(hexByteStringToUint8Array(original));
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { VAA, deserialize } from "../src/vaa";
|
|
2
|
+
import "../src/payloads/tokenBridge";
|
|
3
|
+
import { tokenBridgePayloads } from "../src/payloads/tokenBridge";
|
|
4
|
+
|
|
5
|
+
const cases = [
|
|
6
|
+
"AQAAAAABAMysWsb94YzZxLiJtKr4hcT2qA/+8laXmeZiEtmVZ5kidTdadwYiXfowVtlUtMWNv1PHIU/eH4T1EI/aI6uhW/kBZN0dygAAAAAADgAAAAAAAAAAAAAAAAXKYDfsUfi3Eu0ub6ciGf6udOFTAAAAAAAAAdUBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUk2Xpn9Q9KBiwox09gcDrskCipQADgAAAAAAAAAAAAAAAGYDtKfinfvbYVnDlakV50dXwfsTAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
|
7
|
+
"AQAAAAABAD/A72/ZwTe/pPNRmPLLf3qZY+od9NEqvGEFBv0lHhgJdBmBo4m9cBn2Fb/03XkfFrwM00YQgnmM883tENNnBY8BZOWtSQg8AQAABgAAAAAAAAAAAAAAAGHkTlBspWWebAu6m2eFhvotcpdWAAAAAAAAHWcBAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHoSAAAAAAAAAAAAAAAAAnDySg9PkSFRpfNItP6okDPsDKIkABW2a5rLTM8HWUwGlnaPu04jKXcYMsSSWWEt1y+axX9vtACAAAAAAAAAAAAAAAADUkwZkmKzkCQWf2kwbzS5z2M/+AXsiYmFzaWNfcmVjaXBpZW50Ijp7InJlY2lwaWVudCI6ImMyVnBNVFJqTldVM1pYWjJZM0JvZFdvMGFEaHVjWGxrWm01ek16SXdPWFptYW5SbWFtUndaVGhqIn19",
|
|
8
|
+
];
|
|
9
|
+
|
|
10
|
+
//const original =
|
|
11
|
+
describe("Token Transfer VAA tests", function () {
|
|
12
|
+
it("should correctly deserialize and reserialize a transfer VAA", function () {
|
|
13
|
+
for (const testCase of cases) {
|
|
14
|
+
const vaaBytes = new Uint8Array(Buffer.from(testCase, "base64"));
|
|
15
|
+
let parsed:
|
|
16
|
+
| VAA<"Transfer" | "TransferWithPayload" | "AttestMeta">
|
|
17
|
+
| undefined;
|
|
18
|
+
for (const maybeType of tokenBridgePayloads) {
|
|
19
|
+
try {
|
|
20
|
+
parsed = deserialize(maybeType[0], vaaBytes);
|
|
21
|
+
} catch (e) {}
|
|
22
|
+
}
|
|
23
|
+
if (parsed === undefined) {
|
|
24
|
+
throw new Error(`Couldn't deserialize VAA: ${testCase}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wormhole-foundation/sdk-definitions",
|
|
3
|
+
"version": "0.1.0-beta.3",
|
|
4
|
+
"main": "./dist/cjs/index.js",
|
|
5
|
+
"module": "./dist/esm/index.js",
|
|
6
|
+
"types":"./dist/esm/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "jest --config ../../jest.config.ts __tests__/*.ts",
|
|
9
|
+
"build:cjs":"tsc -p ./tsconfig.cjs.json",
|
|
10
|
+
"build:esm":"tsc -p ./tsconfig.esm.json",
|
|
11
|
+
"build":"npm run build:cjs && npm run build:esm",
|
|
12
|
+
"rebuild":"npm run clean && npm run build:cjs && npm run build:esm",
|
|
13
|
+
"clean": "rm -rf ./dist && rm -f ./*.tsbuildinfo"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@wormhole-foundation/sdk-base": "*",
|
|
17
|
+
"@noble/hashes": "^1.3.1",
|
|
18
|
+
"@noble/secp256k1": "^2.0.0"
|
|
19
|
+
}
|
|
20
|
+
}
|
package/src/address.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChainName,
|
|
3
|
+
isChain,
|
|
4
|
+
PlatformName,
|
|
5
|
+
chainToPlatform,
|
|
6
|
+
ChainToPlatform,
|
|
7
|
+
} from "@wormhole-foundation/sdk-base";
|
|
8
|
+
|
|
9
|
+
//TODO BRRRR circular include!!
|
|
10
|
+
//I have yet to figure out how to get the equivalent of a forward declaration to work (without
|
|
11
|
+
// yet again having to rely on global scope...)
|
|
12
|
+
//I first tried `declare class UniversalAddress {};` but this actually introduces a new, separate
|
|
13
|
+
// type in this module rather than telling the compiler that we already have this type elsewhere
|
|
14
|
+
//I could also create an interface via `interface IUnverisalAddress {}` but that seems like an
|
|
15
|
+
// even worse solution, as is just throwing everything into this file here and just brushing
|
|
16
|
+
// things under the rug by not separating them out.
|
|
17
|
+
import { UniversalAddress } from "./universalAddress";
|
|
18
|
+
|
|
19
|
+
export interface Address {
|
|
20
|
+
//unwrap returns the underlying native address type, e.g.:
|
|
21
|
+
// * a Uint8Array for UniversalAddress
|
|
22
|
+
// * a checksum hex string string for EVM(ethers)
|
|
23
|
+
// * a PublicKey for Solana
|
|
24
|
+
// * etc.
|
|
25
|
+
unwrap(): unknown;
|
|
26
|
+
toString(): string;
|
|
27
|
+
toUint8Array(): Uint8Array;
|
|
28
|
+
toUniversalAddress(): UniversalAddress;
|
|
29
|
+
//static isValidAddress(str: string): boolean;
|
|
30
|
+
|
|
31
|
+
//other ideas:
|
|
32
|
+
//zeroAddress
|
|
33
|
+
//verify(message: Uint8Array, signature: Uint8Array): boolean;
|
|
34
|
+
//static byteSize(): number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
declare global {
|
|
38
|
+
namespace Wormhole {
|
|
39
|
+
export interface PlatformToNativeAddressMapping {}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type MappedPlatforms = keyof Wormhole.PlatformToNativeAddressMapping;
|
|
44
|
+
|
|
45
|
+
type ChainOrPlatformToPlatform<T extends ChainName | PlatformName> =
|
|
46
|
+
T extends ChainName ? ChainToPlatform<T> : T;
|
|
47
|
+
type GetNativeAddress<T extends PlatformName> = T extends MappedPlatforms
|
|
48
|
+
? Wormhole.PlatformToNativeAddressMapping[T]
|
|
49
|
+
: never;
|
|
50
|
+
export type NativeAddress<T extends PlatformName | ChainName> =
|
|
51
|
+
GetNativeAddress<ChainOrPlatformToPlatform<T>>;
|
|
52
|
+
|
|
53
|
+
export type UniversalOrNative<P extends PlatformName> =
|
|
54
|
+
| UniversalAddress
|
|
55
|
+
| NativeAddress<P>;
|
|
56
|
+
|
|
57
|
+
export type ChainAddress<C extends ChainName = ChainName> = {
|
|
58
|
+
readonly chain: C;
|
|
59
|
+
readonly address: UniversalAddress | NativeAddress<C>;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
type NativeAddressCtr = new (
|
|
63
|
+
ua: UniversalAddress | string | Uint8Array
|
|
64
|
+
) => Address;
|
|
65
|
+
|
|
66
|
+
const nativeFactory = new Map<PlatformName, NativeAddressCtr>();
|
|
67
|
+
|
|
68
|
+
export function registerNative<P extends MappedPlatforms>(
|
|
69
|
+
platform: P,
|
|
70
|
+
ctr: NativeAddressCtr
|
|
71
|
+
): void {
|
|
72
|
+
if (nativeFactory.has(platform))
|
|
73
|
+
throw new Error(
|
|
74
|
+
`Native address type for platform ${platform} has already registered`
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
nativeFactory.set(platform, ctr);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function nativeIsRegistered<T extends PlatformName | ChainName>(
|
|
81
|
+
chainOrPlatform: T
|
|
82
|
+
): boolean {
|
|
83
|
+
const platform: PlatformName = isChain(chainOrPlatform)
|
|
84
|
+
? chainToPlatform.get(chainOrPlatform)!
|
|
85
|
+
: chainOrPlatform;
|
|
86
|
+
|
|
87
|
+
return nativeFactory.has(platform);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function toNative<T extends PlatformName | ChainName>(
|
|
91
|
+
chainOrPlatform: T,
|
|
92
|
+
ua: UniversalAddress | string | Uint8Array
|
|
93
|
+
): NativeAddress<T> {
|
|
94
|
+
const platform: PlatformName = isChain(chainOrPlatform)
|
|
95
|
+
? chainToPlatform.get(chainOrPlatform)!
|
|
96
|
+
: chainOrPlatform;
|
|
97
|
+
|
|
98
|
+
const nativeCtr = nativeFactory.get(platform);
|
|
99
|
+
if (!nativeCtr)
|
|
100
|
+
throw new Error(
|
|
101
|
+
`No native address type registered for platform ${platform}`
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
return new nativeCtr(ua) as unknown as NativeAddress<T>;
|
|
105
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ChainName } from "@wormhole-foundation/sdk-base";
|
|
2
|
+
import { VAA } from "./vaa";
|
|
3
|
+
import { UniversalAddress } from "./universalAddress";
|
|
4
|
+
import { SequenceId } from "./types";
|
|
5
|
+
|
|
6
|
+
// Wormhole Message Identifier
|
|
7
|
+
// used to fetch a VAA
|
|
8
|
+
export type WormholeMessageId = {
|
|
9
|
+
chain: ChainName;
|
|
10
|
+
emitter: UniversalAddress;
|
|
11
|
+
sequence: SequenceId;
|
|
12
|
+
};
|
|
13
|
+
export function isWormholeMessageId(
|
|
14
|
+
thing: WormholeMessageId | any
|
|
15
|
+
): thing is WormholeMessageId {
|
|
16
|
+
return (
|
|
17
|
+
(<WormholeMessageId>thing).sequence !== undefined &&
|
|
18
|
+
(<WormholeMessageId>thing).emitter !== undefined &&
|
|
19
|
+
(<WormholeMessageId>thing).chain !== undefined
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type getWormholeAttestation = (id: WormholeMessageId) => Promise<VAA>;
|
|
24
|
+
|
|
25
|
+
// Circle Message Identifier
|
|
26
|
+
// Used to fetch a Circle attestation
|
|
27
|
+
export type CircleMessageId = {
|
|
28
|
+
message: string;
|
|
29
|
+
msgHash: string;
|
|
30
|
+
};
|
|
31
|
+
export function isCircleMessageId(
|
|
32
|
+
thing: CircleMessageId | any
|
|
33
|
+
): thing is CircleMessageId {
|
|
34
|
+
return (<CircleMessageId>thing).msgHash !== undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// No parsing
|
|
38
|
+
export type CircleAttestation = string;
|
|
39
|
+
|
|
40
|
+
export type getCircleAttestation = (
|
|
41
|
+
id: CircleMessageId
|
|
42
|
+
) => Promise<CircleAttestation>;
|
package/src/chain.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { ChainName, PlatformName } from "@wormhole-foundation/sdk-base";
|
|
2
|
+
import { Platform } from "./platform";
|
|
3
|
+
import { RpcConnection } from "./rpc";
|
|
4
|
+
import { AutomaticTokenBridge, TokenBridge } from "./protocols/tokenBridge";
|
|
5
|
+
import { AutomaticCircleBridge, CircleBridge } from "./protocols/cctp";
|
|
6
|
+
|
|
7
|
+
// TODO: there has to be a nicer way to do this
|
|
8
|
+
// This requires the arguments in the function definition come in the same order
|
|
9
|
+
// [chain], [rpc], ...
|
|
10
|
+
|
|
11
|
+
type _omitChain<Fn> = Fn extends (chain: ChainName, ...args: infer A) => infer R
|
|
12
|
+
? (...args: A) => R
|
|
13
|
+
: Fn;
|
|
14
|
+
type _omitRpc<P extends PlatformName, Fn> = Fn extends (
|
|
15
|
+
rpc: RpcConnection<P>,
|
|
16
|
+
...args: infer A
|
|
17
|
+
) => infer R
|
|
18
|
+
? (...args: A) => R
|
|
19
|
+
: Fn;
|
|
20
|
+
|
|
21
|
+
type OmitChainRpc<
|
|
22
|
+
P extends PlatformName,
|
|
23
|
+
F extends keyof Platform<P>
|
|
24
|
+
> = _omitRpc<P, _omitChain<Platform<P>[F]>>;
|
|
25
|
+
|
|
26
|
+
type OmitRpc<P extends PlatformName, F extends keyof Platform<P>> = _omitRpc<
|
|
27
|
+
P,
|
|
28
|
+
Platform<P>[F]
|
|
29
|
+
>;
|
|
30
|
+
|
|
31
|
+
type OmitChain<
|
|
32
|
+
P extends PlatformName,
|
|
33
|
+
F extends keyof Platform<P>
|
|
34
|
+
> = _omitChain<Platform<P>[F]>;
|
|
35
|
+
|
|
36
|
+
export abstract class ChainContext<P extends PlatformName> {
|
|
37
|
+
// Cached Protocol clients
|
|
38
|
+
protected tokenBridge?: TokenBridge<P>;
|
|
39
|
+
protected autoTokenBridge?: AutomaticTokenBridge<P>;
|
|
40
|
+
protected circleBridge?: CircleBridge<P>;
|
|
41
|
+
protected autoCircleBridge?: AutomaticCircleBridge<P>;
|
|
42
|
+
|
|
43
|
+
constructor(readonly platform: Platform<P>, readonly chain: ChainName) {}
|
|
44
|
+
|
|
45
|
+
abstract getRpc(): RpcConnection<P>;
|
|
46
|
+
|
|
47
|
+
// Utils for platform specific queries
|
|
48
|
+
getDecimals: OmitChainRpc<P, "getDecimals"> = (token) => {
|
|
49
|
+
return this.platform.getDecimals(this.chain, this.getRpc(), token);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
getBalance: OmitChainRpc<P, "getBalance"> = (walletAddr, token) => {
|
|
53
|
+
return this.platform.getBalance(
|
|
54
|
+
this.chain,
|
|
55
|
+
this.getRpc(),
|
|
56
|
+
walletAddr,
|
|
57
|
+
token
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Get details about the transaction
|
|
62
|
+
parseTransaction: OmitChainRpc<P, "parseTransaction"> = (txid) => {
|
|
63
|
+
return this.platform.parseTransaction(this.chain, this.getRpc(), txid);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Take a native address and convert it to a UniversalAddress
|
|
67
|
+
parseAddress: OmitChain<P, "parseAddress"> = (address) => {
|
|
68
|
+
return this.platform.parseAddress(this.chain, address);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Send a transaction and wait for it to be confirmed
|
|
72
|
+
sendWait: OmitRpc<P, "sendWait"> = (stxns) => {
|
|
73
|
+
return this.platform.sendWait(this.getRpc(), stxns);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// protocols
|
|
77
|
+
getTokenBridge: OmitRpc<P, "getTokenBridge"> = async () => {
|
|
78
|
+
this.tokenBridge = this.tokenBridge
|
|
79
|
+
? this.tokenBridge
|
|
80
|
+
: await this.platform.getTokenBridge(this.getRpc());
|
|
81
|
+
return this.tokenBridge;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
getAutomaticTokenBridge: OmitRpc<P, "getAutomaticTokenBridge"> = async () => {
|
|
85
|
+
this.autoTokenBridge = this.autoTokenBridge
|
|
86
|
+
? this.autoTokenBridge
|
|
87
|
+
: await this.platform.getAutomaticTokenBridge(this.getRpc());
|
|
88
|
+
return this.autoTokenBridge;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
getCircleBridge: OmitRpc<P, "getCircleBridge"> = async () => {
|
|
92
|
+
this.circleBridge = this.circleBridge
|
|
93
|
+
? this.circleBridge
|
|
94
|
+
: await this.platform.getCircleBridge(this.getRpc());
|
|
95
|
+
return this.circleBridge;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
getAutomaticCircleBridge: OmitRpc<P, "getAutomaticCircleBridge"> =
|
|
99
|
+
async () => {
|
|
100
|
+
this.autoCircleBridge = this.autoCircleBridge
|
|
101
|
+
? this.autoCircleBridge
|
|
102
|
+
: await this.platform.getAutomaticCircleBridge(this.getRpc());
|
|
103
|
+
return this.autoCircleBridge;
|
|
104
|
+
};
|
|
105
|
+
}
|
package/src/contracts.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ChainName, Network, contracts } from "@wormhole-foundation/sdk-base";
|
|
2
|
+
|
|
3
|
+
export type Contracts = {
|
|
4
|
+
coreBridge?: string;
|
|
5
|
+
tokenBridge?: string;
|
|
6
|
+
nftBridge?: string;
|
|
7
|
+
relayer?: string;
|
|
8
|
+
cctp?: contracts.CircleContracts;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export function getContracts(n: Network, c: ChainName): Contracts {
|
|
12
|
+
const ct: Contracts = {
|
|
13
|
+
coreBridge: contracts.coreBridge.get(n, c),
|
|
14
|
+
tokenBridge: contracts.tokenBridge.get(n, c),
|
|
15
|
+
nftBridge: contracts.nftBridge.get(n, c),
|
|
16
|
+
relayer: contracts.relayer.get(n, c),
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
if (contracts.circleContracts.has(n, c)) {
|
|
20
|
+
ct.cctp = contracts.circleContracts.get(n, c);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return ct;
|
|
24
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Make sure payloads are registered
|
|
2
|
+
import "./payloads/connect";
|
|
3
|
+
import "./payloads/relayer";
|
|
4
|
+
import "./payloads/governance";
|
|
5
|
+
import "./payloads/tokenBridge";
|
|
6
|
+
|
|
7
|
+
export * from "./address";
|
|
8
|
+
export * from "./universalAddress";
|
|
9
|
+
export * from "./unsignedTransaction";
|
|
10
|
+
export * from "./vaa";
|
|
11
|
+
export * from "./utils";
|
|
12
|
+
export * from "./relayer";
|
|
13
|
+
export * from "./platform";
|
|
14
|
+
export * from "./chain";
|
|
15
|
+
export * from "./contracts";
|
|
16
|
+
export * from "./signature";
|
|
17
|
+
export * from "./rpc";
|
|
18
|
+
export * from "./attestation";
|
|
19
|
+
export * from "./types";
|
|
20
|
+
|
|
21
|
+
export * from "./protocols/core";
|
|
22
|
+
export * from "./protocols/tokenBridge";
|
|
23
|
+
export * from "./protocols/cctp";
|
|
24
|
+
|
|
25
|
+
export * as testing from "./testing";
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {
|
|
2
|
+
chains,
|
|
3
|
+
toChainId,
|
|
4
|
+
chainToChainId,
|
|
5
|
+
chainIdToChain,
|
|
6
|
+
CustomConversion,
|
|
7
|
+
FixedConversion,
|
|
8
|
+
UintLayoutItem,
|
|
9
|
+
ChainName,
|
|
10
|
+
} from "@wormhole-foundation/sdk-base";
|
|
11
|
+
|
|
12
|
+
const chainItemBase = { binary: "uint", size: 2 } as const;
|
|
13
|
+
|
|
14
|
+
type AllowNull<T, B extends boolean> = B extends true ? T | null : T;
|
|
15
|
+
|
|
16
|
+
export const chainItem = <
|
|
17
|
+
C extends readonly ChainName[] = typeof chains,
|
|
18
|
+
N extends boolean = false
|
|
19
|
+
>(opts?: {
|
|
20
|
+
allowedChains?: C;
|
|
21
|
+
allowNull?: N;
|
|
22
|
+
}) =>
|
|
23
|
+
({
|
|
24
|
+
...chainItemBase,
|
|
25
|
+
custom: {
|
|
26
|
+
to: (val: number): AllowNull<C[number], N> => {
|
|
27
|
+
if (val === 0) {
|
|
28
|
+
if (!opts?.allowNull)
|
|
29
|
+
throw new Error(
|
|
30
|
+
"ChainId 0 is not valid for this module and action"
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
return null as AllowNull<C[number], N>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const chain = chainIdToChain(toChainId(val));
|
|
37
|
+
const allowedChains = opts?.allowedChains ?? chains;
|
|
38
|
+
if (!allowedChains.includes(chain))
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Chain ${chain} not in allowed chains ${allowedChains}`
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
return chain;
|
|
44
|
+
},
|
|
45
|
+
from: (val: AllowNull<C[number], N>): number =>
|
|
46
|
+
val == null ? 0 : chainToChainId(val),
|
|
47
|
+
} satisfies CustomConversion<number, AllowNull<C[number], N>>,
|
|
48
|
+
} as const satisfies Omit<UintLayoutItem, "name">);
|
|
49
|
+
|
|
50
|
+
export const fixedChainItem = <C extends ChainName>(chain: C) =>
|
|
51
|
+
({
|
|
52
|
+
...chainItemBase,
|
|
53
|
+
custom: {
|
|
54
|
+
to: chain,
|
|
55
|
+
from: chainToChainId(chain),
|
|
56
|
+
} satisfies FixedConversion<number, C>,
|
|
57
|
+
} as const satisfies Omit<UintLayoutItem, "name">);
|