@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.
Files changed (50) hide show
  1. package/README.md +3 -0
  2. package/__tests__/connectVAA.ts +21 -0
  3. package/__tests__/governanceVaa.ts +139 -0
  4. package/__tests__/relayerVaa.ts +24 -0
  5. package/__tests__/transferVaa.ts +28 -0
  6. package/package.json +20 -0
  7. package/src/address.ts +105 -0
  8. package/src/attestation.ts +42 -0
  9. package/src/chain.ts +105 -0
  10. package/src/contracts.ts +24 -0
  11. package/src/index.ts +25 -0
  12. package/src/layout-items/amount.ts +6 -0
  13. package/src/layout-items/chain.ts +57 -0
  14. package/src/layout-items/guardianSet.ts +6 -0
  15. package/src/layout-items/index.ts +7 -0
  16. package/src/layout-items/payloadId.ts +10 -0
  17. package/src/layout-items/sequence.ts +6 -0
  18. package/src/layout-items/signature.ts +27 -0
  19. package/src/layout-items/universalAddress.ts +14 -0
  20. package/src/payloads/connect.ts +52 -0
  21. package/src/payloads/governance.ts +219 -0
  22. package/src/payloads/relayer.ts +101 -0
  23. package/src/payloads/tokenBridge.ts +93 -0
  24. package/src/platform.ts +57 -0
  25. package/src/protocols/cctp.ts +47 -0
  26. package/src/protocols/core.ts +10 -0
  27. package/src/protocols/tokenBridge.ts +70 -0
  28. package/src/relayer.ts +50 -0
  29. package/src/rpc.ts +16 -0
  30. package/src/signature.ts +26 -0
  31. package/src/testing/README.md +4 -0
  32. package/src/testing/index.ts +2 -0
  33. package/src/testing/mocks/api.ts +9 -0
  34. package/src/testing/mocks/chain.ts +18 -0
  35. package/src/testing/mocks/contracts.ts +57 -0
  36. package/src/testing/mocks/index.ts +5 -0
  37. package/src/testing/mocks/platform.ts +146 -0
  38. package/src/testing/mocks/rpc.ts +12 -0
  39. package/src/testing/mocks/tokenBridge.ts +68 -0
  40. package/src/testing/utils/address.ts +65 -0
  41. package/src/testing/utils/index.ts +2 -0
  42. package/src/testing/utils/vaa.ts +13 -0
  43. package/src/types.ts +73 -0
  44. package/src/universalAddress.ts +57 -0
  45. package/src/unsignedTransaction.ts +12 -0
  46. package/src/utils.ts +4 -0
  47. package/src/vaa.ts +236 -0
  48. package/tsconfig.cjs.json +8 -0
  49. package/tsconfig.esm.json +8 -0
  50. package/typedoc.json +4 -0
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ should subsume/replace files from old sdk:
2
+ * vaa/parser
3
+ * mock
@@ -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
+ }
@@ -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,6 @@
1
+ import { UintLayoutItem } from "@wormhole-foundation/sdk-base";
2
+
3
+ export const amountItem = {
4
+ binary: "uint",
5
+ size: 32,
6
+ } as const satisfies Omit<UintLayoutItem, "name">;
@@ -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">);
@@ -0,0 +1,6 @@
1
+ import { UintLayoutItem } from "@wormhole-foundation/sdk-base";
2
+
3
+ export const guardianSetItem = {
4
+ binary: "uint",
5
+ size: 4,
6
+ } as const satisfies Omit<UintLayoutItem, "name">;
@@ -0,0 +1,7 @@
1
+ export * from "./amount";
2
+ export * from "./chain";
3
+ export * from "./guardianSet";
4
+ export * from "./payloadId";
5
+ export * from "./sequence";
6
+ export * from "./signature";
7
+ export * from "./universalAddress";
@@ -0,0 +1,10 @@
1
+ import { UintLayoutItem } from "@wormhole-foundation/sdk-base";
2
+
3
+ export const payloadIdItem = <ID extends number>(id: ID) =>
4
+ ({
5
+ name: "payloadId",
6
+ binary: "uint",
7
+ size: 1,
8
+ custom: id,
9
+ omit: true,
10
+ } as const satisfies UintLayoutItem);
@@ -0,0 +1,6 @@
1
+ import { UintLayoutItem } from "@wormhole-foundation/sdk-base";
2
+
3
+ export const sequenceItem = {
4
+ binary: "uint",
5
+ size: 8,
6
+ } as const satisfies Omit<UintLayoutItem, "name">;