@wiimdy/openfunderse-sdk 0.1.1

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 (62) hide show
  1. package/README.md +43 -0
  2. package/dist/attestation-verifier.d.ts +11 -0
  3. package/dist/attestation-verifier.js +60 -0
  4. package/dist/attestation.d.ts +4 -0
  5. package/dist/attestation.js +16 -0
  6. package/dist/canonical.d.ts +3 -0
  7. package/dist/canonical.js +37 -0
  8. package/dist/dist_bak_vercel_repro/attestation-verifier.d.ts +11 -0
  9. package/dist/dist_bak_vercel_repro/attestation-verifier.js +60 -0
  10. package/dist/dist_bak_vercel_repro/attestation.d.ts +4 -0
  11. package/dist/dist_bak_vercel_repro/attestation.js +16 -0
  12. package/dist/dist_bak_vercel_repro/canonical.d.ts +3 -0
  13. package/dist/dist_bak_vercel_repro/canonical.js +37 -0
  14. package/dist/dist_bak_vercel_repro/eip712.d.ts +112 -0
  15. package/dist/dist_bak_vercel_repro/eip712.js +74 -0
  16. package/dist/dist_bak_vercel_repro/erc1271.d.ts +4 -0
  17. package/dist/dist_bak_vercel_repro/erc1271.js +24 -0
  18. package/dist/dist_bak_vercel_repro/execution-data.d.ts +3 -0
  19. package/dist/dist_bak_vercel_repro/execution-data.js +66 -0
  20. package/dist/dist_bak_vercel_repro/hash.d.ts +16 -0
  21. package/dist/dist_bak_vercel_repro/hash.js +67 -0
  22. package/dist/dist_bak_vercel_repro/index.d.ts +14 -0
  23. package/dist/dist_bak_vercel_repro/index.js +14 -0
  24. package/dist/dist_bak_vercel_repro/nadfun-types.d.ts +29 -0
  25. package/dist/dist_bak_vercel_repro/nadfun-types.js +1 -0
  26. package/dist/dist_bak_vercel_repro/ordering.d.ts +5 -0
  27. package/dist/dist_bak_vercel_repro/ordering.js +22 -0
  28. package/dist/dist_bak_vercel_repro/relayer-utils.d.ts +29 -0
  29. package/dist/dist_bak_vercel_repro/relayer-utils.js +108 -0
  30. package/dist/dist_bak_vercel_repro/scope.d.ts +5 -0
  31. package/dist/dist_bak_vercel_repro/scope.js +26 -0
  32. package/dist/dist_bak_vercel_repro/types.d.ts +106 -0
  33. package/dist/dist_bak_vercel_repro/types.js +1 -0
  34. package/dist/dist_bak_vercel_repro/validate.d.ts +2 -0
  35. package/dist/dist_bak_vercel_repro/validate.js +12 -0
  36. package/dist/dist_bak_vercel_repro/weighted-attestation.d.ts +19 -0
  37. package/dist/dist_bak_vercel_repro/weighted-attestation.js +62 -0
  38. package/dist/eip712.d.ts +112 -0
  39. package/dist/eip712.js +74 -0
  40. package/dist/erc1271.d.ts +4 -0
  41. package/dist/erc1271.js +24 -0
  42. package/dist/execution-data.d.ts +3 -0
  43. package/dist/execution-data.js +66 -0
  44. package/dist/hash.d.ts +16 -0
  45. package/dist/hash.js +67 -0
  46. package/dist/index.d.ts +14 -0
  47. package/dist/index.js +14 -0
  48. package/dist/nadfun-types.d.ts +29 -0
  49. package/dist/nadfun-types.js +1 -0
  50. package/dist/ordering.d.ts +5 -0
  51. package/dist/ordering.js +22 -0
  52. package/dist/relayer-utils.d.ts +29 -0
  53. package/dist/relayer-utils.js +108 -0
  54. package/dist/scope.d.ts +5 -0
  55. package/dist/scope.js +26 -0
  56. package/dist/types.d.ts +106 -0
  57. package/dist/types.js +1 -0
  58. package/dist/validate.d.ts +2 -0
  59. package/dist/validate.js +12 -0
  60. package/dist/weighted-attestation.d.ts +19 -0
  61. package/dist/weighted-attestation.js +62 -0
  62. package/package.json +32 -0
@@ -0,0 +1,67 @@
1
+ import { encodeAbiParameters, keccak256, parseAbiParameters, toHex } from "viem";
2
+ import { canonicalClaim, canonicalIntent } from "./canonical.js";
3
+ import { assertStrictlySortedHex, uniqueSortedBytes32Hex } from "./ordering.js";
4
+ import { assertUint16, assertUint64 } from "./validate.js";
5
+ export function claimHash(payload) {
6
+ const v = canonicalClaim(payload);
7
+ assertUint64(v.timestamp, "timestamp");
8
+ return keccak256(encodeAbiParameters(parseAbiParameters("string schemaId,string sourceType,string sourceRef,string selector,string extracted,string extractedType,uint64 timestamp,bytes32 responseHash,string evidenceType,string evidenceURI,address crawler,string notes"), [
9
+ v.schemaId,
10
+ v.sourceType,
11
+ v.sourceRef,
12
+ v.selector,
13
+ v.extracted,
14
+ v.extractedType,
15
+ v.timestamp,
16
+ v.responseHash,
17
+ v.evidenceType,
18
+ v.evidenceURI,
19
+ v.crawler,
20
+ v.notes ?? ""
21
+ ]));
22
+ }
23
+ export function intentHash(intent) {
24
+ const v = canonicalIntent(intent);
25
+ assertUint64(v.deadline, "deadline");
26
+ assertUint16(v.maxSlippageBps, "maxSlippageBps");
27
+ return keccak256(encodeAbiParameters(parseAbiParameters("string intentVersion,address vault,string action,address tokenIn,address tokenOut,uint256 amountIn,uint256 minAmountOut,uint64 deadline,uint16 maxSlippageBps,bytes32 snapshotHash"), [
28
+ v.intentVersion,
29
+ v.vault,
30
+ v.action,
31
+ v.tokenIn,
32
+ v.tokenOut,
33
+ v.amountIn,
34
+ v.minAmountOut,
35
+ v.deadline,
36
+ Number(v.maxSlippageBps),
37
+ v.snapshotHash
38
+ ]));
39
+ }
40
+ export function snapshotHash(epochId, orderedClaimHashes) {
41
+ assertUint64(epochId, "epochId");
42
+ assertStrictlySortedHex(orderedClaimHashes);
43
+ return keccak256(encodeAbiParameters(parseAbiParameters("uint64 epochId,bytes32[] orderedClaimHashes"), [epochId, orderedClaimHashes]));
44
+ }
45
+ export function canonicalOrderedClaimHashes(claimHashes) {
46
+ return uniqueSortedBytes32Hex(claimHashes);
47
+ }
48
+ export function snapshotHashFromUnordered(epochId, claimHashes) {
49
+ const orderedClaimHashes = canonicalOrderedClaimHashes(claimHashes);
50
+ return snapshotHash(epochId, orderedClaimHashes);
51
+ }
52
+ export function reasonHash(reason) {
53
+ return keccak256(toHex(reason.normalize("NFC").trim()));
54
+ }
55
+ /**
56
+ * Canonical allowlist hash for intent execution route.
57
+ * Must match ClawCore allowlist verification logic.
58
+ */
59
+ export function intentExecutionAllowlistHash(tokenIn, tokenOut, quoteAmountOut, minAmountOut, adapter, adapterDataHash) {
60
+ return keccak256(encodeAbiParameters(parseAbiParameters("address tokenIn,address tokenOut,uint256 quoteAmountOut,uint256 minAmountOut,address adapter,bytes32 adapterDataHash"), [tokenIn, tokenOut, quoteAmountOut, minAmountOut, adapter, adapterDataHash]));
61
+ }
62
+ /**
63
+ * Helper that hashes raw adapter calldata before building the allowlist hash.
64
+ */
65
+ export function intentExecutionCallHash(tokenIn, tokenOut, quoteAmountOut, minAmountOut, adapter, adapterData) {
66
+ return intentExecutionAllowlistHash(tokenIn, tokenOut, quoteAmountOut, minAmountOut, adapter, keccak256(adapterData));
67
+ }
@@ -0,0 +1,14 @@
1
+ export * from "./types.js";
2
+ export * from "./nadfun-types.js";
3
+ export * from "./canonical.js";
4
+ export * from "./hash.js";
5
+ export * from "./eip712.js";
6
+ export * from "./erc1271.js";
7
+ export * from "./ordering.js";
8
+ export * from "./scope.js";
9
+ export * from "./attestation.js";
10
+ export * from "./validate.js";
11
+ export * from "./attestation-verifier.js";
12
+ export * from "./weighted-attestation.js";
13
+ export * from "./execution-data.js";
14
+ export * from "./relayer-utils.js";
@@ -0,0 +1,14 @@
1
+ export * from "./types.js";
2
+ export * from "./nadfun-types.js";
3
+ export * from "./canonical.js";
4
+ export * from "./hash.js";
5
+ export * from "./eip712.js";
6
+ export * from "./erc1271.js";
7
+ export * from "./ordering.js";
8
+ export * from "./scope.js";
9
+ export * from "./attestation.js";
10
+ export * from "./validate.js";
11
+ export * from "./attestation-verifier.js";
12
+ export * from "./weighted-attestation.js";
13
+ export * from "./execution-data.js";
14
+ export * from "./relayer-utils.js";
@@ -0,0 +1,29 @@
1
+ import { Address, TradeIntent } from "./types.js";
2
+ /**
3
+ * NadFun-specific metadata for offchain intent context.
4
+ * These fields are NOT included in intentHash computation.
5
+ * They provide additional context for strategy/verifier agents.
6
+ */
7
+ export interface NadFunIntentMeta {
8
+ /** Token symbol (e.g., "ABC") */
9
+ tokenSymbol: string;
10
+ /** Bonding curve state: BONDING (pre-graduation) or GRADUATED (post-graduation) */
11
+ curveState: "BONDING" | "GRADUATED";
12
+ /** Bonding curve contract address (valid when curveState === "BONDING") */
13
+ curveAddress: Address;
14
+ /** DEX pool address (valid when curveState === "GRADUATED") */
15
+ dexPoolAddress: Address;
16
+ /** NadFun platform token ID */
17
+ nadfunTokenId: string;
18
+ /** Graduation progress in basis points (0-10000) */
19
+ graduationProgress: bigint;
20
+ }
21
+ /**
22
+ * Extended trade intent combining canonical TradeIntent with NadFun metadata.
23
+ * The intentHash is computed only from TradeIntent fields.
24
+ * Metadata fields are for offchain context and agent decision-making.
25
+ */
26
+ export interface NadFunTradeIntent extends TradeIntent {
27
+ /** NadFun-specific metadata (not included in hash) */
28
+ nadfunMeta: NadFunIntentMeta;
29
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import type { Hex } from "./types.js";
2
+ export declare function sortBytes32Hex(values: Hex[]): Hex[];
3
+ export declare function uniqueSortedBytes32Hex(values: Hex[]): Hex[];
4
+ export declare function isStrictlySortedHex(values: Hex[]): boolean;
5
+ export declare function assertStrictlySortedHex(values: Hex[], label?: string): void;
@@ -0,0 +1,22 @@
1
+ function normalizeHex(value) {
2
+ return value.toLowerCase();
3
+ }
4
+ export function sortBytes32Hex(values) {
5
+ return [...values].map(normalizeHex).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
6
+ }
7
+ export function uniqueSortedBytes32Hex(values) {
8
+ return [...new Set(sortBytes32Hex(values))];
9
+ }
10
+ export function isStrictlySortedHex(values) {
11
+ for (let i = 1; i < values.length; i += 1) {
12
+ if (values[i - 1].toLowerCase() >= values[i].toLowerCase()) {
13
+ return false;
14
+ }
15
+ }
16
+ return true;
17
+ }
18
+ export function assertStrictlySortedHex(values, label = "orderedClaimHashes") {
19
+ if (!isStrictlySortedHex(values)) {
20
+ throw new Error(`${label} must be strictly sorted ascending with no duplicates`);
21
+ }
22
+ }
@@ -0,0 +1,29 @@
1
+ import type { CanonicalClaimRecord, CanonicalIntentRecord, ClaimPayload, CoreExecutionRequestInput, Hex, IntentExecutionRouteInput, IntentConstraints, TradeIntent } from "./types.js";
2
+ export declare function buildCanonicalClaimRecord(input: {
3
+ payload: ClaimPayload;
4
+ epochId: bigint;
5
+ }): CanonicalClaimRecord;
6
+ export declare function buildIntentConstraints(input: {
7
+ allowlistHash: Hex;
8
+ maxSlippageBps: bigint;
9
+ maxNotional: bigint;
10
+ deadline: bigint;
11
+ }): IntentConstraints;
12
+ export declare function buildCanonicalIntentRecord(input: {
13
+ intent: TradeIntent;
14
+ allowlistHash: Hex;
15
+ maxNotional: bigint;
16
+ now?: bigint;
17
+ }): CanonicalIntentRecord;
18
+ export declare function buildCanonicalSnapshotRecord(input: {
19
+ epochId: bigint;
20
+ claimHashes: Hex[];
21
+ }): {
22
+ epochId: bigint;
23
+ snapshotHash: `0x${string}`;
24
+ };
25
+ export declare function buildIntentAllowlistHashFromRoute(route: IntentExecutionRouteInput): Hex;
26
+ export declare function buildCoreExecutionRequestFromIntent(input: {
27
+ intent: TradeIntent;
28
+ executionRoute: IntentExecutionRouteInput;
29
+ }): CoreExecutionRequestInput;
@@ -0,0 +1,108 @@
1
+ import { keccak256 } from "viem";
2
+ import { canonicalClaim, canonicalIntent } from "./canonical.js";
3
+ import { claimHash, intentExecutionAllowlistHash, intentHash, snapshotHashFromUnordered } from "./hash.js";
4
+ import { assertUint16, assertUint64 } from "./validate.js";
5
+ function assertPositive(value, label) {
6
+ if (value <= 0n) {
7
+ throw new Error(`${label} must be positive`);
8
+ }
9
+ }
10
+ function assertHex32(value, label) {
11
+ if (!/^0x[0-9a-fA-F]{64}$/.test(value)) {
12
+ throw new Error(`${label} must be 0x-prefixed 32-byte hex`);
13
+ }
14
+ }
15
+ export function buildCanonicalClaimRecord(input) {
16
+ assertUint64(input.epochId, "epochId");
17
+ assertUint64(input.payload.timestamp, "timestamp");
18
+ const payload = canonicalClaim(input.payload);
19
+ const hash = claimHash(payload);
20
+ return {
21
+ payload,
22
+ epochId: input.epochId,
23
+ claimHash: hash
24
+ };
25
+ }
26
+ export function buildIntentConstraints(input) {
27
+ assertHex32(input.allowlistHash, "allowlistHash");
28
+ assertUint16(input.maxSlippageBps, "maxSlippageBps");
29
+ assertUint64(input.deadline, "deadline");
30
+ assertPositive(input.maxNotional, "maxNotional");
31
+ return {
32
+ allowlistHash: input.allowlistHash,
33
+ maxSlippageBps: input.maxSlippageBps,
34
+ maxNotional: input.maxNotional,
35
+ deadline: input.deadline
36
+ };
37
+ }
38
+ export function buildCanonicalIntentRecord(input) {
39
+ const intent = canonicalIntent(input.intent);
40
+ assertUint64(intent.deadline, "deadline");
41
+ assertUint16(intent.maxSlippageBps, "maxSlippageBps");
42
+ assertPositive(intent.amountIn, "amountIn");
43
+ assertPositive(intent.minAmountOut, "minAmountOut");
44
+ if (intent.deadline <= (input.now ?? BigInt(Math.floor(Date.now() / 1000)))) {
45
+ throw new Error("intent deadline is expired");
46
+ }
47
+ const constraints = buildIntentConstraints({
48
+ allowlistHash: input.allowlistHash,
49
+ maxSlippageBps: intent.maxSlippageBps,
50
+ maxNotional: input.maxNotional,
51
+ deadline: intent.deadline
52
+ });
53
+ return {
54
+ intent,
55
+ intentHash: intentHash(intent),
56
+ constraints
57
+ };
58
+ }
59
+ export function buildCanonicalSnapshotRecord(input) {
60
+ assertUint64(input.epochId, "epochId");
61
+ if (input.claimHashes.length === 0) {
62
+ throw new Error("claimHashes must not be empty");
63
+ }
64
+ const hash = snapshotHashFromUnordered(input.epochId, input.claimHashes);
65
+ return {
66
+ epochId: input.epochId,
67
+ snapshotHash: hash
68
+ };
69
+ }
70
+ export function buildIntentAllowlistHashFromRoute(route) {
71
+ assertPositive(route.quoteAmountOut, "quoteAmountOut");
72
+ assertPositive(route.minAmountOut, "minAmountOut");
73
+ const adapterDataHash = route.adapterDataHash ??
74
+ (route.adapterData ? keccak256(route.adapterData) : undefined);
75
+ if (!adapterDataHash) {
76
+ throw new Error("adapterData or adapterDataHash is required");
77
+ }
78
+ assertHex32(adapterDataHash, "adapterDataHash");
79
+ return intentExecutionAllowlistHash(route.tokenIn, route.tokenOut, route.quoteAmountOut, route.minAmountOut, route.adapter, adapterDataHash);
80
+ }
81
+ export function buildCoreExecutionRequestFromIntent(input) {
82
+ const { intent, executionRoute } = input;
83
+ assertPositive(intent.amountIn, "amountIn");
84
+ assertPositive(intent.minAmountOut, "minAmountOut");
85
+ assertPositive(executionRoute.quoteAmountOut, "quoteAmountOut");
86
+ assertPositive(executionRoute.minAmountOut, "route.minAmountOut");
87
+ if (executionRoute.tokenIn.toLowerCase() !== intent.tokenIn.toLowerCase()) {
88
+ throw new Error("executionRoute.tokenIn must match intent.tokenIn");
89
+ }
90
+ if (executionRoute.tokenOut.toLowerCase() !== intent.tokenOut.toLowerCase()) {
91
+ throw new Error("executionRoute.tokenOut must match intent.tokenOut");
92
+ }
93
+ if (executionRoute.minAmountOut !== intent.minAmountOut) {
94
+ throw new Error("executionRoute.minAmountOut must match intent.minAmountOut");
95
+ }
96
+ if (!executionRoute.adapterData) {
97
+ throw new Error("executionRoute.adapterData is required for execution");
98
+ }
99
+ return {
100
+ tokenIn: executionRoute.tokenIn,
101
+ tokenOut: executionRoute.tokenOut,
102
+ amountIn: intent.amountIn,
103
+ quoteAmountOut: executionRoute.quoteAmountOut,
104
+ minAmountOut: executionRoute.minAmountOut,
105
+ adapter: executionRoute.adapter,
106
+ adapterData: executionRoute.adapterData
107
+ };
108
+ }
@@ -0,0 +1,5 @@
1
+ import type { Hex, ProtocolScope } from "./types.js";
2
+ export declare function canonicalScope(input: ProtocolScope): ProtocolScope;
3
+ export declare function scopeKey(input: ProtocolScope): string;
4
+ export declare function assertSameScope(expected: ProtocolScope, received: ProtocolScope): void;
5
+ export declare function scopedSnapshotHash(scope: ProtocolScope, snapshotHash: Hex): Hex;
@@ -0,0 +1,26 @@
1
+ import { encodeAbiParameters, keccak256, parseAbiParameters } from "viem";
2
+ function normalizeScopeText(value) {
3
+ return value.normalize("NFC").trim();
4
+ }
5
+ export function canonicalScope(input) {
6
+ return {
7
+ fundId: normalizeScopeText(input.fundId),
8
+ roomId: normalizeScopeText(input.roomId),
9
+ epochId: input.epochId
10
+ };
11
+ }
12
+ export function scopeKey(input) {
13
+ const v = canonicalScope(input);
14
+ return `${v.fundId}:${v.roomId}:${v.epochId.toString(10)}`;
15
+ }
16
+ export function assertSameScope(expected, received) {
17
+ const left = scopeKey(expected);
18
+ const right = scopeKey(received);
19
+ if (left !== right) {
20
+ throw new Error(`scope mismatch: expected=${left}, received=${right}`);
21
+ }
22
+ }
23
+ export function scopedSnapshotHash(scope, snapshotHash) {
24
+ const v = canonicalScope(scope);
25
+ return keccak256(encodeAbiParameters(parseAbiParameters("string fundId,string roomId,uint64 epochId,bytes32 snapshotHash"), [v.fundId, v.roomId, v.epochId, snapshotHash]));
26
+ }
@@ -0,0 +1,106 @@
1
+ export type Hex = `0x${string}`;
2
+ export type Address = `0x${string}`;
3
+ export interface ClaimPayload {
4
+ schemaId: string;
5
+ sourceType: string;
6
+ sourceRef: string;
7
+ selector: string;
8
+ extracted: string;
9
+ extractedType: string;
10
+ timestamp: bigint;
11
+ responseHash: Hex;
12
+ evidenceType: string;
13
+ evidenceURI: string;
14
+ crawler: Address;
15
+ notes?: string;
16
+ }
17
+ export interface TradeIntent {
18
+ intentVersion: string;
19
+ vault: Address;
20
+ action: "BUY" | "SELL";
21
+ tokenIn: Address;
22
+ tokenOut: Address;
23
+ amountIn: bigint;
24
+ minAmountOut: bigint;
25
+ deadline: bigint;
26
+ maxSlippageBps: bigint;
27
+ snapshotHash: Hex;
28
+ reason?: string;
29
+ }
30
+ export interface Eip712DomainInput {
31
+ name: string;
32
+ version: string;
33
+ chainId: bigint;
34
+ verifyingContract: Address;
35
+ }
36
+ export interface ProtocolScope {
37
+ fundId: string;
38
+ roomId: string;
39
+ epochId: bigint;
40
+ }
41
+ export type SubjectType = "CLAIM" | "INTENT";
42
+ export interface AttestationMeta {
43
+ verifier: Address;
44
+ expiresAt: bigint;
45
+ nonce: bigint;
46
+ }
47
+ export interface ClaimAttestationDraft extends AttestationMeta {
48
+ claimHash: Hex;
49
+ epochId: bigint;
50
+ }
51
+ export interface IntentAttestationDraft extends AttestationMeta {
52
+ intentHash: Hex;
53
+ }
54
+ export interface SignedAttestation<TSubject extends SubjectType, TMessage> {
55
+ subjectType: TSubject;
56
+ subjectHash: Hex;
57
+ message: TMessage;
58
+ signature: Hex;
59
+ }
60
+ export type ExecutionAction = "BUY" | "SELL";
61
+ export type ExecutionVenue = "NADFUN_BONDING_CURVE" | "NADFUN_DEX";
62
+ export interface NadfunExecutionDataV1 {
63
+ version: 1;
64
+ action: ExecutionAction;
65
+ venue: ExecutionVenue;
66
+ router: Address;
67
+ recipient: Address;
68
+ token: Address;
69
+ deadline: bigint;
70
+ amountOutMin: bigint;
71
+ extra: Hex;
72
+ }
73
+ export interface IntentConstraints {
74
+ allowlistHash: Hex;
75
+ maxSlippageBps: bigint;
76
+ maxNotional: bigint;
77
+ deadline: bigint;
78
+ }
79
+ export interface IntentExecutionRouteInput {
80
+ tokenIn: Address;
81
+ tokenOut: Address;
82
+ quoteAmountOut: bigint;
83
+ minAmountOut: bigint;
84
+ adapter: Address;
85
+ adapterData?: Hex;
86
+ adapterDataHash?: Hex;
87
+ }
88
+ export interface CoreExecutionRequestInput {
89
+ tokenIn: Address;
90
+ tokenOut: Address;
91
+ amountIn: bigint;
92
+ quoteAmountOut: bigint;
93
+ minAmountOut: bigint;
94
+ adapter: Address;
95
+ adapterData: Hex;
96
+ }
97
+ export interface CanonicalClaimRecord {
98
+ payload: ClaimPayload;
99
+ epochId: bigint;
100
+ claimHash: Hex;
101
+ }
102
+ export interface CanonicalIntentRecord {
103
+ intent: TradeIntent;
104
+ intentHash: Hex;
105
+ constraints: IntentConstraints;
106
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare function assertUint16(value: bigint, label: string): void;
2
+ export declare function assertUint64(value: bigint, label: string): void;
@@ -0,0 +1,12 @@
1
+ const UINT16_MAX = (1n << 16n) - 1n;
2
+ const UINT64_MAX = (1n << 64n) - 1n;
3
+ export function assertUint16(value, label) {
4
+ if (value < 0n || value > UINT16_MAX) {
5
+ throw new Error(`${label} must be uint16`);
6
+ }
7
+ }
8
+ export function assertUint64(value, label) {
9
+ if (value < 0n || value > UINT64_MAX) {
10
+ throw new Error(`${label} must be uint64`);
11
+ }
12
+ }
@@ -0,0 +1,19 @@
1
+ import type { Address } from "./types.js";
2
+ export interface ValidatorWeight {
3
+ validator: Address;
4
+ weight: bigint;
5
+ }
6
+ export interface WeightMapOptions {
7
+ allowZeroWeight?: boolean;
8
+ }
9
+ export interface WeightedThresholdState {
10
+ totalWeight: bigint;
11
+ attestedWeight: bigint;
12
+ thresholdWeight: bigint;
13
+ met: boolean;
14
+ }
15
+ export declare function buildValidatorWeightMap(entries: ValidatorWeight[], options?: WeightMapOptions): Map<string, bigint>;
16
+ export declare function totalValidatorWeight(weightMap: Map<string, bigint>): bigint;
17
+ export declare function attestedWeight(attesters: Address[], weightMap: Map<string, bigint>): bigint;
18
+ export declare function reachedWeightedThreshold(attesters: Address[], weightMap: Map<string, bigint>, thresholdWeight: bigint): boolean;
19
+ export declare function weightedThresholdState(attesters: Address[], weightMap: Map<string, bigint>, thresholdWeight: bigint): WeightedThresholdState;
@@ -0,0 +1,62 @@
1
+ function toKey(address) {
2
+ return address.toLowerCase();
3
+ }
4
+ export function buildValidatorWeightMap(entries, options = {}) {
5
+ const allowZeroWeight = options.allowZeroWeight ?? false;
6
+ const map = new Map();
7
+ for (const entry of entries) {
8
+ if (entry.weight < 0n) {
9
+ throw new Error("weight must be non-negative");
10
+ }
11
+ if (!allowZeroWeight && entry.weight === 0n) {
12
+ throw new Error("weight must be positive");
13
+ }
14
+ const key = toKey(entry.validator);
15
+ if (map.has(key)) {
16
+ throw new Error(`duplicate validator weight entry: ${entry.validator}`);
17
+ }
18
+ map.set(key, entry.weight);
19
+ }
20
+ return map;
21
+ }
22
+ export function totalValidatorWeight(weightMap) {
23
+ let total = 0n;
24
+ for (const weight of weightMap.values()) {
25
+ total += weight;
26
+ }
27
+ return total;
28
+ }
29
+ export function attestedWeight(attesters, weightMap) {
30
+ let total = 0n;
31
+ const seen = new Set();
32
+ for (const attester of attesters) {
33
+ const key = toKey(attester);
34
+ if (seen.has(key))
35
+ continue;
36
+ seen.add(key);
37
+ const weight = weightMap.get(key);
38
+ if (weight !== undefined) {
39
+ total += weight;
40
+ }
41
+ }
42
+ return total;
43
+ }
44
+ export function reachedWeightedThreshold(attesters, weightMap, thresholdWeight) {
45
+ if (thresholdWeight <= 0n) {
46
+ throw new Error("thresholdWeight must be positive");
47
+ }
48
+ return attestedWeight(attesters, weightMap) >= thresholdWeight;
49
+ }
50
+ export function weightedThresholdState(attesters, weightMap, thresholdWeight) {
51
+ if (thresholdWeight <= 0n) {
52
+ throw new Error("thresholdWeight must be positive");
53
+ }
54
+ const totalWeight = totalValidatorWeight(weightMap);
55
+ const reachedWeight = attestedWeight(attesters, weightMap);
56
+ return {
57
+ totalWeight,
58
+ attestedWeight: reachedWeight,
59
+ thresholdWeight,
60
+ met: reachedWeight >= thresholdWeight
61
+ };
62
+ }
@@ -0,0 +1,112 @@
1
+ import type { Address, Eip712DomainInput, Hex } from "./types.js";
2
+ export declare const CLAIM_ATTESTATION_TYPES: {
3
+ readonly ClaimAttestation: readonly [{
4
+ readonly name: "claimHash";
5
+ readonly type: "bytes32";
6
+ }, {
7
+ readonly name: "epochId";
8
+ readonly type: "uint64";
9
+ }, {
10
+ readonly name: "verifier";
11
+ readonly type: "address";
12
+ }, {
13
+ readonly name: "expiresAt";
14
+ readonly type: "uint64";
15
+ }, {
16
+ readonly name: "nonce";
17
+ readonly type: "uint256";
18
+ }];
19
+ };
20
+ export declare const INTENT_ATTESTATION_TYPES: {
21
+ readonly IntentAttestation: readonly [{
22
+ readonly name: "intentHash";
23
+ readonly type: "bytes32";
24
+ }, {
25
+ readonly name: "verifier";
26
+ readonly type: "address";
27
+ }, {
28
+ readonly name: "expiresAt";
29
+ readonly type: "uint64";
30
+ }, {
31
+ readonly name: "nonce";
32
+ readonly type: "uint256";
33
+ }];
34
+ };
35
+ export interface ClaimAttestationMessage {
36
+ claimHash: Hex;
37
+ epochId: bigint;
38
+ verifier: Address;
39
+ expiresAt: bigint;
40
+ nonce: bigint;
41
+ }
42
+ export interface IntentAttestationMessage {
43
+ intentHash: Hex;
44
+ verifier: Address;
45
+ expiresAt: bigint;
46
+ nonce: bigint;
47
+ }
48
+ export declare function toEip712Domain(input: Eip712DomainInput): {
49
+ name: string;
50
+ version: string;
51
+ chainId: bigint;
52
+ verifyingContract: `0x${string}`;
53
+ };
54
+ export declare function claimAttestationTypedData(domain: Eip712DomainInput, message: ClaimAttestationMessage): {
55
+ domain: {
56
+ name: string;
57
+ version: string;
58
+ chainId: bigint;
59
+ verifyingContract: `0x${string}`;
60
+ };
61
+ types: {
62
+ readonly ClaimAttestation: readonly [{
63
+ readonly name: "claimHash";
64
+ readonly type: "bytes32";
65
+ }, {
66
+ readonly name: "epochId";
67
+ readonly type: "uint64";
68
+ }, {
69
+ readonly name: "verifier";
70
+ readonly type: "address";
71
+ }, {
72
+ readonly name: "expiresAt";
73
+ readonly type: "uint64";
74
+ }, {
75
+ readonly name: "nonce";
76
+ readonly type: "uint256";
77
+ }];
78
+ };
79
+ primaryType: "ClaimAttestation";
80
+ message: ClaimAttestationMessage;
81
+ };
82
+ export declare function intentAttestationTypedData(domain: Eip712DomainInput, message: IntentAttestationMessage): {
83
+ domain: {
84
+ name: string;
85
+ version: string;
86
+ chainId: bigint;
87
+ verifyingContract: `0x${string}`;
88
+ };
89
+ types: {
90
+ readonly IntentAttestation: readonly [{
91
+ readonly name: "intentHash";
92
+ readonly type: "bytes32";
93
+ }, {
94
+ readonly name: "verifier";
95
+ readonly type: "address";
96
+ }, {
97
+ readonly name: "expiresAt";
98
+ readonly type: "uint64";
99
+ }, {
100
+ readonly name: "nonce";
101
+ readonly type: "uint256";
102
+ }];
103
+ };
104
+ primaryType: "IntentAttestation";
105
+ message: IntentAttestationMessage;
106
+ };
107
+ export declare function claimAttestationDigest(domain: Eip712DomainInput, message: ClaimAttestationMessage): Hex;
108
+ export declare function intentAttestationDigest(domain: Eip712DomainInput, message: IntentAttestationMessage): Hex;
109
+ export declare function verifyClaimAttestation(domain: Eip712DomainInput, message: ClaimAttestationMessage, signature: Hex): Promise<boolean>;
110
+ export declare function verifyIntentAttestation(domain: Eip712DomainInput, message: IntentAttestationMessage, signature: Hex): Promise<boolean>;
111
+ export declare function recoverClaimAttester(domain: Eip712DomainInput, message: ClaimAttestationMessage, signature: Hex): Promise<Address>;
112
+ export declare function recoverIntentAttester(domain: Eip712DomainInput, message: IntentAttestationMessage, signature: Hex): Promise<Address>;