@wormhole-foundation/sdk-base 0.1.4 → 0.1.6-beta

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 (82) hide show
  1. package/dist/cjs/constants/circle.d.ts +16 -16
  2. package/dist/cjs/constants/circle.d.ts.map +1 -1
  3. package/dist/cjs/constants/circle.js +3 -0
  4. package/dist/cjs/constants/circle.js.map +1 -1
  5. package/dist/cjs/constants/contracts/circle.d.ts +6 -1
  6. package/dist/cjs/constants/contracts/circle.d.ts.map +1 -1
  7. package/dist/cjs/constants/contracts/circle.js +10 -1
  8. package/dist/cjs/constants/contracts/circle.js.map +1 -1
  9. package/dist/cjs/constants/contracts/index.d.ts +91 -16
  10. package/dist/cjs/constants/contracts/index.d.ts.map +1 -1
  11. package/dist/cjs/constants/finality.d.ts +8 -0
  12. package/dist/cjs/constants/finality.d.ts.map +1 -1
  13. package/dist/cjs/constants/finality.js +40 -1
  14. package/dist/cjs/constants/finality.js.map +1 -1
  15. package/dist/cjs/utils/amount.d.ts +9 -0
  16. package/dist/cjs/utils/amount.d.ts.map +1 -0
  17. package/dist/cjs/utils/amount.js +35 -0
  18. package/dist/cjs/utils/amount.js.map +1 -0
  19. package/dist/cjs/utils/index.d.ts +1 -0
  20. package/dist/cjs/utils/index.d.ts.map +1 -1
  21. package/dist/cjs/utils/index.js +1 -0
  22. package/dist/cjs/utils/index.js.map +1 -1
  23. package/dist/cjs/utils/layout/deserialize.d.ts.map +1 -1
  24. package/dist/cjs/utils/layout/deserialize.js +9 -11
  25. package/dist/cjs/utils/layout/deserialize.js.map +1 -1
  26. package/dist/cjs/utils/layout/discriminate.d.ts.map +1 -1
  27. package/dist/cjs/utils/layout/discriminate.js +17 -18
  28. package/dist/cjs/utils/layout/discriminate.js.map +1 -1
  29. package/dist/cjs/utils/layout/layout.d.ts +13 -9
  30. package/dist/cjs/utils/layout/layout.d.ts.map +1 -1
  31. package/dist/cjs/utils/layout/layout.js +7 -14
  32. package/dist/cjs/utils/layout/layout.js.map +1 -1
  33. package/dist/cjs/utils/layout/serialize.d.ts +2 -2
  34. package/dist/cjs/utils/layout/serialize.d.ts.map +1 -1
  35. package/dist/cjs/utils/layout/serialize.js +18 -24
  36. package/dist/cjs/utils/layout/serialize.js.map +1 -1
  37. package/dist/esm/constants/circle.d.ts +16 -16
  38. package/dist/esm/constants/circle.d.ts.map +1 -1
  39. package/dist/esm/constants/circle.js +3 -0
  40. package/dist/esm/constants/circle.js.map +1 -1
  41. package/dist/esm/constants/contracts/circle.d.ts +6 -1
  42. package/dist/esm/constants/contracts/circle.d.ts.map +1 -1
  43. package/dist/esm/constants/contracts/circle.js +10 -1
  44. package/dist/esm/constants/contracts/circle.js.map +1 -1
  45. package/dist/esm/constants/contracts/index.d.ts +91 -16
  46. package/dist/esm/constants/contracts/index.d.ts.map +1 -1
  47. package/dist/esm/constants/finality.d.ts +8 -0
  48. package/dist/esm/constants/finality.d.ts.map +1 -1
  49. package/dist/esm/constants/finality.js +39 -0
  50. package/dist/esm/constants/finality.js.map +1 -1
  51. package/dist/esm/utils/amount.d.ts +9 -0
  52. package/dist/esm/utils/amount.d.ts.map +1 -0
  53. package/dist/esm/utils/amount.js +31 -0
  54. package/dist/esm/utils/amount.js.map +1 -0
  55. package/dist/esm/utils/index.d.ts +1 -0
  56. package/dist/esm/utils/index.d.ts.map +1 -1
  57. package/dist/esm/utils/index.js +1 -0
  58. package/dist/esm/utils/index.js.map +1 -1
  59. package/dist/esm/utils/layout/deserialize.d.ts.map +1 -1
  60. package/dist/esm/utils/layout/deserialize.js +10 -12
  61. package/dist/esm/utils/layout/deserialize.js.map +1 -1
  62. package/dist/esm/utils/layout/discriminate.d.ts.map +1 -1
  63. package/dist/esm/utils/layout/discriminate.js +18 -19
  64. package/dist/esm/utils/layout/discriminate.js.map +1 -1
  65. package/dist/esm/utils/layout/layout.d.ts +13 -9
  66. package/dist/esm/utils/layout/layout.d.ts.map +1 -1
  67. package/dist/esm/utils/layout/layout.js +4 -13
  68. package/dist/esm/utils/layout/layout.js.map +1 -1
  69. package/dist/esm/utils/layout/serialize.d.ts +2 -2
  70. package/dist/esm/utils/layout/serialize.d.ts.map +1 -1
  71. package/dist/esm/utils/layout/serialize.js +19 -25
  72. package/dist/esm/utils/layout/serialize.js.map +1 -1
  73. package/package.json +1 -1
  74. package/src/constants/circle.ts +3 -0
  75. package/src/constants/contracts/circle.ts +10 -1
  76. package/src/constants/finality.ts +41 -0
  77. package/src/utils/amount.ts +38 -0
  78. package/src/utils/index.ts +2 -1
  79. package/src/utils/layout/deserialize.ts +17 -15
  80. package/src/utils/layout/discriminate.ts +30 -25
  81. package/src/utils/layout/layout.ts +22 -26
  82. package/src/utils/layout/serialize.ts +25 -25
@@ -2,11 +2,14 @@ import {
2
2
  Layout,
3
3
  LayoutItem,
4
4
  LayoutToType,
5
- LayoutItemToType,
6
5
  FixedPrimitiveBytesLayoutItem,
7
6
  FixedValueBytesLayoutItem,
8
7
  CustomConversion,
9
8
  UintSizeToPrimitive,
9
+ UintType,
10
+ BytesType,
11
+ isUintType,
12
+ isBytesType,
10
13
  numberMaxSize,
11
14
  } from "./layout";
12
15
 
@@ -109,9 +112,9 @@ function deserializeLayoutItem(
109
112
  let fixedFrom;
110
113
  let fixedTo;
111
114
  if (item.custom !== undefined) {
112
- if (item.custom instanceof Uint8Array)
115
+ if (isBytesType(item.custom))
113
116
  fixedFrom = item.custom;
114
- else if (item.custom.from instanceof Uint8Array) {
117
+ else if (isBytesType(item.custom.from)) {
115
118
  fixedFrom = item.custom.from;
116
119
  fixedTo = item.custom.to;
117
120
  }
@@ -139,7 +142,7 @@ function deserializeLayoutItem(
139
142
  return [fixedTo ?? fixedFrom, newOffset];
140
143
  }
141
144
 
142
- type narrowedCustom = CustomConversion<Uint8Array, any>;
145
+ type narrowedCustom = CustomConversion<BytesType, any>;
143
146
  return [
144
147
  item.custom !== undefined ? (item.custom as narrowedCustom).to(value) : value,
145
148
  newOffset
@@ -148,21 +151,20 @@ function deserializeLayoutItem(
148
151
  case "uint": {
149
152
  const [value, newOffset] = deserializeUint(encoded, offset, item.size);
150
153
 
151
- if (item.custom !== undefined) {
152
- if (typeof item.custom === "number" || typeof item.custom === "bigint") {
153
- checkUintEquals(item.custom, value);
154
- return [item.custom, newOffset];
155
- }
156
- else if (typeof item.custom.from === "number" || typeof item.custom.from === "bigint") {
157
- checkUintEquals(item.custom.from, value);
158
- return [item.custom.to, newOffset];
159
- }
154
+ if (isUintType(item.custom)) {
155
+ checkUintEquals(item.custom, value);
156
+ return [item.custom, newOffset];
157
+ }
158
+
159
+ if (isUintType(item?.custom?.from)) {
160
+ checkUintEquals(item!.custom!.from, value);
161
+ return [item!.custom!.to, newOffset];
160
162
  }
161
163
 
162
- //narrowing to CustomConver<number | bigint, any> is a bit hacky here, since the true type
164
+ //narrowing to CustomConver<UintType, any> is a bit hacky here, since the true type
163
165
  // would be CustomConver<number, any> | CustomConver<bigint, any>, but then we'd have to
164
166
  // further tease that apart still for no real gain...
165
- type narrowedCustom = CustomConversion<number | bigint, any>;
167
+ type narrowedCustom = CustomConversion<UintType, any>;
166
168
  return [
167
169
  item.custom !== undefined ? (item.custom as narrowedCustom).to(value) : value,
168
170
  newOffset
@@ -2,7 +2,8 @@ import {
2
2
  Layout,
3
3
  LayoutItem,
4
4
  LengthPrefixedBytesLayoutItem,
5
- isPrimitiveType,
5
+ isUintType,
6
+ isBytesType,
6
7
  } from "./layout";
7
8
 
8
9
  import { serializeUint } from "./serialize";
@@ -20,7 +21,7 @@ type FixedBytes = (readonly [BytePos, Uint8Array])[];
20
21
  // bound or Infinity) in anticipation of a future switch layout item that might contain multiple
21
22
  // sublayouts which, unlike arrays currently, could all be bounded but potentially with
22
23
  // different sizes
23
- type Bounds = readonly [Size, Size];
24
+ type Bounds = [Size, Size];
24
25
 
25
26
  function arrayToBitset(arr: readonly number[]): Bitset {
26
27
  return arr.reduce((bit, i) => bit | BigInt(1) << BigInt(i), BigInt(0));
@@ -44,11 +45,11 @@ function count(candidates: Candidates) {
44
45
 
45
46
  function layoutItemMeta(
46
47
  item: LayoutItem,
47
- offset: BytePos,
48
+ offset: BytePos | null,
48
49
  fixedBytes: FixedBytes,
49
50
  ): Bounds {
50
51
  function knownFixed(size: Size, serialized: Uint8Array): Bounds {
51
- if (Number.isFinite(offset))
52
+ if (offset !== null)
52
53
  fixedBytes.push([offset, serialized]);
53
54
 
54
55
  return [size, size];
@@ -65,11 +66,11 @@ function layoutItemMeta(
65
66
  if ("size" in item && item.size !== undefined)
66
67
  return [item.size, item.size];
67
68
 
68
- if (item?.custom instanceof Uint8Array)
69
+ if (isBytesType(item?.custom))
69
70
  return knownFixed(item.custom.length, item.custom);
70
71
 
71
- if (item?.custom?.from instanceof Uint8Array)
72
- return knownFixed(item.custom.from.length, item.custom.from);
72
+ if (isBytesType(item?.custom?.from))
73
+ return knownFixed(item!.custom!.from.length, item!.custom!.from);
73
74
 
74
75
  //TODO typescript should be able to infer that at this point the only possible remaining
75
76
  // type for item is LengthPrefixedBytesLayoutItem, but for some reason it doesn't
@@ -77,9 +78,16 @@ function layoutItemMeta(
77
78
  return [item.lengthSize !== undefined ? item.lengthSize : 0, Infinity];
78
79
  }
79
80
  case "uint": {
80
- if (isPrimitiveType(item.custom)) {
81
+ const fixedVal =
82
+ isUintType(item.custom)
83
+ ? item.custom
84
+ : isUintType(item?.custom?.from)
85
+ ? item!.custom!.from
86
+ : null;
87
+
88
+ if (fixedVal !== null) {
81
89
  const serialized = new Uint8Array(item.size);
82
- serializeUint(serialized, 0, item.custom, item.size)
90
+ serializeUint(serialized, 0, fixedVal, item.size)
83
91
  return knownFixed(item.size, serialized);
84
92
  }
85
93
 
@@ -90,16 +98,17 @@ function layoutItemMeta(
90
98
 
91
99
  function createLayoutMeta(
92
100
  layout: Layout,
93
- offset: BytePos,
101
+ offset: BytePos | null,
94
102
  fixedBytes: FixedBytes
95
103
  ): Bounds {
96
104
  let bounds = [0, 0] as Bounds;
97
105
  for (const item of layout) {
98
- bounds = layoutItemMeta(item, offset, fixedBytes)
99
- //we need the cast because of course mapping tuples to tuples is an unsolved problem in TS:
100
- //https://stackoverflow.com/questions/57913193/how-to-use-array-map-with-tuples-in-typescript#answer-57913509
101
- .map((b, i) => bounds[i] + b) as unknown as Bounds;
102
- offset = bounds[0] === bounds[1] ? bounds[0] : Infinity;
106
+ const itemSize = layoutItemMeta(item, offset, fixedBytes);
107
+ bounds[0] += itemSize[0];
108
+ bounds[1] += itemSize[1];
109
+ //if the bounds don't agree then we can't reliably predict the offset of subsequent items
110
+ if (offset !== null)
111
+ offset = itemSize[0] === itemSize[1] ? offset + itemSize[0] : null;
103
112
  }
104
113
  return bounds;
105
114
  }
@@ -279,15 +288,9 @@ function generateLayoutDiscriminator(
279
288
  type Strategy = [BytePos, Candidates, Map<number, Candidates>] | "size" | "indistinguishable";
280
289
 
281
290
  let distinguishable = true;
282
- let firstStrategy: Strategy | undefined;
283
291
  const strategies = new Map<Candidates, Strategy>();
284
292
  const candidatesBySize = new Map<Size, Candidates[]>();
285
293
  const addStrategy = (candidates: Candidates, strategy: Strategy) => {
286
- if (firstStrategy === undefined) {
287
- firstStrategy = strategy;
288
- return;
289
- }
290
-
291
294
  strategies.set(candidates, strategy);
292
295
  if (!candidatesBySize.has(count(candidates)))
293
296
  candidatesBySize.set(count(candidates), []);
@@ -394,8 +397,12 @@ function generateLayoutDiscriminator(
394
397
 
395
398
  return [distinguishable, (encoded: Uint8Array) => {
396
399
  let candidates = allLayouts;
397
- let strategy = firstStrategy!;
398
- while (strategy !== "indistinguishable") {
400
+
401
+ for (
402
+ let strategy = strategies.get(candidates)!;
403
+ strategy !== "indistinguishable";
404
+ strategy = strategies.get(candidates) ?? findSmallestSuperSetStrategy(candidates)
405
+ ) {
399
406
  if (strategy === "size")
400
407
  candidates &= layoutsWithSize(encoded.length);
401
408
  else {
@@ -414,8 +421,6 @@ function generateLayoutDiscriminator(
414
421
 
415
422
  if (count(candidates) <= 1)
416
423
  return bitsetToArray(candidates);
417
-
418
- strategy = strategies.get(candidates) ?? findSmallestSuperSetStrategy(candidates);
419
424
  }
420
425
 
421
426
  return bitsetToArray(candidates);
@@ -1,20 +1,16 @@
1
1
  //TODO:
2
- // * make FixedItem recursive
3
- // * implement a swtich layout item that maps different values (versions) to different sublayouts
4
- // * implement a method that determines the total size of a layout, if all items have known size
5
- // * implement a method that determines the offsets of items in a layout (if all preceding items
6
- // have known, fixed size (i.e. no arrays))
7
- // * leverage the above to implement deserialization of just a set of fields of a layout
8
- // * implement a method that takes several layouts and a serialized piece of data and quickly
9
- // determines which layouts this payload conforms to (might be 0 or even all!). Should leverage
10
- // the above methods and fixed values in the layout to quickly exclude candidates.
11
- // * implement a method that allows "raw" serialization and deserialization" i.e. that skips all the
12
- // custom conversions (should only be used for testing!) or even just partitions i.e. slices
13
- // the encoded Uint8Array
14
-
15
- export type PrimitiveType = number | bigint | Uint8Array;
2
+ // * implement a switch layout item that maps different values (versions) to different sublayouts
3
+
4
+ export type UintType = number | bigint;
5
+ export const isUintType = (x: any): x is UintType =>
6
+ typeof x === "number" || typeof x === "bigint";
7
+
8
+ export type BytesType = Uint8Array;
9
+ export const isBytesType = (x: any): x is BytesType => x instanceof Uint8Array;
10
+
11
+ export type PrimitiveType = UintType | BytesType;
16
12
  export const isPrimitiveType = (x: any): x is PrimitiveType =>
17
- typeof x === "number" || typeof x === "bigint" || x instanceof Uint8Array;
13
+ isUintType(x) || isBytesType(x);
18
14
 
19
15
  export type BinaryLiterals = "uint" | "bytes" | "array" | "object";
20
16
 
@@ -57,26 +53,26 @@ interface OptionalToFromCustom<T extends PrimitiveType> {
57
53
  };
58
54
 
59
55
  //size: number of bytes used to encode the item
60
- interface UintLayoutItemBase<T extends number | bigint> extends LayoutItemBase<"uint"> {
56
+ interface UintLayoutItemBase<T extends UintType> extends LayoutItemBase<"uint"> {
61
57
  size: T extends bigint ? number : NumberSize,
62
58
  };
63
59
 
64
- export interface PrimitiveFixedUintLayoutItem<T extends number | bigint>
60
+ export interface PrimitiveFixedUintLayoutItem<T extends UintType>
65
61
  extends UintLayoutItemBase<T>, PrimitiveFixedCustom<T> {};
66
62
 
67
- export interface OptionalToFromUintLayoutItem<T extends number | bigint>
63
+ export interface OptionalToFromUintLayoutItem<T extends UintType>
68
64
  extends UintLayoutItemBase<T>, OptionalToFromCustom<T> {};
69
65
 
70
66
  export interface FixedPrimitiveBytesLayoutItem
71
- extends LayoutItemBase<"bytes">, PrimitiveFixedCustom<Uint8Array> {};
67
+ extends LayoutItemBase<"bytes">, PrimitiveFixedCustom<BytesType> {};
72
68
 
73
69
  export interface FixedValueBytesLayoutItem extends LayoutItemBase<"bytes"> {
74
- readonly custom: FixedConversion<Uint8Array, any>,
70
+ readonly custom: FixedConversion<BytesType, any>,
75
71
  };
76
72
 
77
73
  export interface FixedSizeBytesLayoutItem extends LayoutItemBase<"bytes"> {
78
74
  readonly size: number,
79
- readonly custom?: CustomConversion<Uint8Array, any>,
75
+ readonly custom?: CustomConversion<BytesType, any>,
80
76
  };
81
77
 
82
78
  //length size: number of bytes used to encode the preceeding length field which in turn
@@ -84,7 +80,7 @@ export interface FixedSizeBytesLayoutItem extends LayoutItemBase<"bytes"> {
84
80
  // undefined means it will consume the rest of the data
85
81
  export interface LengthPrefixedBytesLayoutItem extends LayoutItemBase<"bytes"> {
86
82
  readonly lengthSize?: NumberSize,
87
- readonly custom?: CustomConversion<Uint8Array, any>,
83
+ readonly custom?: CustomConversion<BytesType, any>,
88
84
  };
89
85
 
90
86
  export interface ArrayLayoutItem extends LayoutItemBase<"array"> {
@@ -124,7 +120,7 @@ export type LayoutItemToType<I extends LayoutItem> =
124
120
  : [I] extends [ObjectLayoutItem]
125
121
  ? LayoutToType<I["layout"]>
126
122
  : [I] extends [UintLayoutItem]
127
- ? I["custom"] extends number | bigint
123
+ ? I["custom"] extends UintType
128
124
  ? I["custom"]
129
125
  : I["custom"] extends CustomConversion<any, infer ToType>
130
126
  ? ToType
@@ -132,9 +128,9 @@ export type LayoutItemToType<I extends LayoutItem> =
132
128
  ? ToType
133
129
  : UintSizeToPrimitive<I["size"]>
134
130
  : [I] extends [BytesLayoutItem]
135
- ? I["custom"] extends CustomConversion<Uint8Array, infer ToType>
131
+ ? I["custom"] extends CustomConversion<BytesType, infer ToType>
136
132
  ? ToType
137
- : I["custom"] extends FixedConversion<Uint8Array, infer ToType>
133
+ : I["custom"] extends FixedConversion<BytesType, infer ToType>
138
134
  ? ToType
139
- : Uint8Array
135
+ : BytesType //this also covers FixedValueBytesLayoutItem (Uint8Arrays don't support literals)
140
136
  : never;
@@ -8,6 +8,9 @@ import {
8
8
  FixedPrimitiveBytesLayoutItem,
9
9
  FixedValueBytesLayoutItem,
10
10
  CustomConversion,
11
+ UintType,
12
+ isUintType,
13
+ isBytesType,
11
14
  numberMaxSize,
12
15
  } from "./layout";
13
16
  import { checkUint8ArrayDeeplyEqual, checkUint8ArraySize, checkUintEquals } from "./utils";
@@ -57,12 +60,11 @@ const calcLayoutSize = (
57
60
  return acc;
58
61
  }
59
62
  case "bytes": {
60
- if (item.custom !== undefined) {
61
- if (item.custom instanceof Uint8Array)
62
- return acc + item.custom.length;
63
- else if (item.custom.from instanceof Uint8Array)
64
- return acc + item.custom.from.length;
65
- }
63
+ if (isBytesType(item.custom))
64
+ return acc + item.custom.length;
65
+
66
+ if (isBytesType(item?.custom?.from))
67
+ return acc + item!.custom!.from.length;
66
68
 
67
69
  item = item as FixedSizeBytesLayoutItem | LengthPrefixedBytesLayoutItem;
68
70
 
@@ -91,7 +93,7 @@ const calcLayoutSize = (
91
93
  export function serializeUint(
92
94
  encoded: Uint8Array,
93
95
  offset: number,
94
- val: number | bigint,
96
+ val: UintType,
95
97
  bytes: number,
96
98
  ): number {
97
99
  if (val < 0 || (typeof val === "number" && !Number.isInteger(val)))
@@ -135,17 +137,16 @@ function serializeLayoutItem(
135
137
  }
136
138
  case "bytes": {
137
139
  const value = (() => {
138
- if (item.custom !== undefined) {
139
- if (item.custom instanceof Uint8Array) {
140
- if (!(item as { omit?: boolean })?.omit)
141
- checkUint8ArrayDeeplyEqual(item.custom, data);
142
- return item.custom;
143
- }
144
- if (item.custom.from instanceof Uint8Array)
145
- //no proper way to deeply check equality of item.custom.to and data in JS
146
- return item.custom.from;
140
+ if (isBytesType(item.custom)) {
141
+ if (!(item as { omit?: boolean })?.omit)
142
+ checkUint8ArrayDeeplyEqual(item.custom, data);
143
+ return item.custom;
147
144
  }
148
145
 
146
+ if (isBytesType(item?.custom?.from))
147
+ //no proper way to deeply check equality of item.custom.to and data in JS
148
+ return item!.custom!.from;
149
+
149
150
  item = item as
150
151
  Exclude<typeof item, FixedPrimitiveBytesLayoutItem | FixedValueBytesLayoutItem>;
151
152
  const ret = item.custom !== undefined ? item.custom.from(data) : data;
@@ -163,17 +164,16 @@ function serializeLayoutItem(
163
164
  }
164
165
  case "uint": {
165
166
  const value = (() => {
166
- if (item.custom !== undefined) {
167
- if (typeof item.custom == "number" || typeof item.custom === "bigint") {
168
- if (!(item as { omit?: boolean })?.omit)
169
- checkUintEquals(item.custom, data);
170
- return item.custom;
171
- }
172
- if (typeof item.custom.from == "number" || typeof item.custom.from === "bigint")
173
- //no proper way to deeply check equality of item.custom.to and data in JS
174
- return item.custom.from;
167
+ if (isUintType(item.custom)) {
168
+ if (!(item as { omit?: boolean })?.omit)
169
+ checkUintEquals(item.custom, data);
170
+ return item.custom;
175
171
  }
176
172
 
173
+ if (isUintType(item?.custom?.from))
174
+ //no proper way to deeply check equality of item.custom.to and data in JS
175
+ return item!.custom!.from;
176
+
177
177
  type narrowedCustom = CustomConversion<number, any> | CustomConversion<bigint, any>;
178
178
  return item.custom !== undefined ? (item.custom as narrowedCustom).from(data) : data;
179
179
  })();