@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
package/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # @claw/protocol-sdk
2
+
3
+ Claw의 공통 프로토콜 SDK (최소 범위):
4
+
5
+ ## Role
6
+ - Monorepo canonical utility layer shared by contracts tests, relayer, and agents.
7
+ - Owns protocol hashing/typed-data rules so all components use identical verification logic.
8
+
9
+ - canonical hashing (`claimHash`, `intentHash`, `snapshotHash`)
10
+ - EIP-712 attestation typed data + verify/recover
11
+ - weighted threshold 유틸
12
+ - intent execution route 해시 유틸 (`intentExecutionAllowlistHash`, `intentExecutionCallHash`)
13
+ - NadFun adapter 실행데이터 인코딩/디코딩 (`encodeNadfunExecutionDataV1`)
14
+
15
+ ## 목적
16
+
17
+ 다른 서비스(릴레이어/봇/프론트/컨트랙트 테스트)가 **동일한 intent 규격과 해시 규칙**을 공유하도록 강제.
18
+
19
+ ## 설치
20
+
21
+ ```bash
22
+ npm install @claw/protocol-sdk
23
+ ```
24
+
25
+ ## 로컬 개발
26
+
27
+ ```bash
28
+ cd /Users/ham-yunsig/Documents/github/claw-validation-market/packages/sdk
29
+ npm install
30
+ npm test
31
+ ```
32
+
33
+ ## 핵심 사용 예
34
+
35
+ ```ts
36
+ import {
37
+ intentHash,
38
+ intentExecutionCallHash,
39
+ encodeNadfunExecutionDataV1,
40
+ intentAttestationTypedData,
41
+ verifyIntentAttestation
42
+ } from "@claw/protocol-sdk";
43
+ ```
@@ -0,0 +1,11 @@
1
+ import { type ClaimAttestationMessage, type IntentAttestationMessage } from "./eip712.js";
2
+ import type { Eip712DomainInput, Hex } from "./types.js";
3
+ export interface VerificationResult {
4
+ ok: boolean;
5
+ digest?: Hex;
6
+ recovered?: `0x${string}`;
7
+ error?: string;
8
+ }
9
+ export declare function verifyClaimAttestationEnvelope(domain: Eip712DomainInput, message: ClaimAttestationMessage, signature: Hex): Promise<VerificationResult>;
10
+ export declare function verifyIntentAttestationEnvelope(domain: Eip712DomainInput, message: IntentAttestationMessage, signature: Hex): Promise<VerificationResult>;
11
+ export declare function reachedThreshold(validCount: number, threshold: number): boolean;
@@ -0,0 +1,60 @@
1
+ import { claimAttestationDigest, intentAttestationDigest, recoverClaimAttester, recoverIntentAttester } from "./eip712.js";
2
+ import { assertNotExpired } from "./attestation.js";
3
+ async function verifyEnvelope(verifier, computeDigest, recoverAddress) {
4
+ try {
5
+ const digest = computeDigest();
6
+ const recovered = await recoverAddress();
7
+ if (recovered.toLowerCase() !== verifier.toLowerCase()) {
8
+ return {
9
+ ok: false,
10
+ digest,
11
+ recovered,
12
+ error: "signature does not recover claimed verifier"
13
+ };
14
+ }
15
+ return {
16
+ ok: true,
17
+ digest,
18
+ recovered
19
+ };
20
+ }
21
+ catch (error) {
22
+ return {
23
+ ok: false,
24
+ error: error instanceof Error ? error.message : String(error)
25
+ };
26
+ }
27
+ }
28
+ export async function verifyClaimAttestationEnvelope(domain, message, signature) {
29
+ try {
30
+ assertNotExpired(message.expiresAt);
31
+ }
32
+ catch (error) {
33
+ return {
34
+ ok: false,
35
+ error: error instanceof Error ? error.message : String(error)
36
+ };
37
+ }
38
+ return verifyEnvelope(message.verifier, () => claimAttestationDigest(domain, message), () => recoverClaimAttester(domain, message, signature));
39
+ }
40
+ export async function verifyIntentAttestationEnvelope(domain, message, signature) {
41
+ try {
42
+ assertNotExpired(message.expiresAt);
43
+ }
44
+ catch (error) {
45
+ return {
46
+ ok: false,
47
+ error: error instanceof Error ? error.message : String(error)
48
+ };
49
+ }
50
+ return verifyEnvelope(message.verifier, () => intentAttestationDigest(domain, message), () => recoverIntentAttester(domain, message, signature));
51
+ }
52
+ export function reachedThreshold(validCount, threshold) {
53
+ if (!Number.isInteger(validCount) || validCount < 0) {
54
+ throw new Error("validCount must be a non-negative integer");
55
+ }
56
+ if (!Number.isInteger(threshold) || threshold <= 0) {
57
+ throw new Error("threshold must be a positive integer");
58
+ }
59
+ return validCount >= threshold;
60
+ }
@@ -0,0 +1,4 @@
1
+ export declare function unixNow(): bigint;
2
+ export declare function isExpired(expiresAt: bigint, now?: bigint): boolean;
3
+ export declare function assertNotExpired(expiresAt: bigint, now?: bigint): void;
4
+ export declare function assertNonceStrictlyIncreases(lastNonce: bigint | null, incomingNonce: bigint): void;
@@ -0,0 +1,16 @@
1
+ export function unixNow() {
2
+ return BigInt(Math.floor(Date.now() / 1000));
3
+ }
4
+ export function isExpired(expiresAt, now = unixNow()) {
5
+ return expiresAt <= now;
6
+ }
7
+ export function assertNotExpired(expiresAt, now = unixNow()) {
8
+ if (isExpired(expiresAt, now)) {
9
+ throw new Error(`signature expired: expiresAt=${expiresAt.toString(10)}, now=${now.toString(10)}`);
10
+ }
11
+ }
12
+ export function assertNonceStrictlyIncreases(lastNonce, incomingNonce) {
13
+ if (lastNonce !== null && incomingNonce <= lastNonce) {
14
+ throw new Error(`nonce must strictly increase: last=${lastNonce.toString(10)}, incoming=${incomingNonce.toString(10)}`);
15
+ }
16
+ }
@@ -0,0 +1,3 @@
1
+ import type { ClaimPayload, TradeIntent } from "./types.js";
2
+ export declare function canonicalClaim(input: ClaimPayload): ClaimPayload;
3
+ export declare function canonicalIntent(input: TradeIntent): TradeIntent;
@@ -0,0 +1,37 @@
1
+ import { getAddress } from "viem";
2
+ function normalizeText(value) {
3
+ return value.normalize("NFC").trim();
4
+ }
5
+ function normalizeAddress(value) {
6
+ return getAddress(value);
7
+ }
8
+ export function canonicalClaim(input) {
9
+ return {
10
+ ...input,
11
+ schemaId: normalizeText(input.schemaId),
12
+ sourceType: normalizeText(input.sourceType),
13
+ sourceRef: normalizeText(input.sourceRef),
14
+ selector: normalizeText(input.selector),
15
+ extracted: normalizeText(input.extracted),
16
+ extractedType: normalizeText(input.extractedType),
17
+ evidenceType: normalizeText(input.evidenceType),
18
+ evidenceURI: normalizeText(input.evidenceURI),
19
+ crawler: normalizeAddress(input.crawler),
20
+ notes: input.notes === undefined ? undefined : normalizeText(input.notes)
21
+ };
22
+ }
23
+ export function canonicalIntent(input) {
24
+ const normalizedAction = normalizeText(input.action).toUpperCase();
25
+ if (normalizedAction !== "BUY" && normalizedAction !== "SELL") {
26
+ throw new Error(`invalid action: ${input.action}`);
27
+ }
28
+ return {
29
+ ...input,
30
+ intentVersion: normalizeText(input.intentVersion),
31
+ vault: normalizeAddress(input.vault),
32
+ action: normalizedAction,
33
+ tokenIn: normalizeAddress(input.tokenIn),
34
+ tokenOut: normalizeAddress(input.tokenOut),
35
+ reason: input.reason === undefined ? undefined : normalizeText(input.reason)
36
+ };
37
+ }
@@ -0,0 +1,11 @@
1
+ import { type ClaimAttestationMessage, type IntentAttestationMessage } from "./eip712.js";
2
+ import type { Eip712DomainInput, Hex } from "./types.js";
3
+ export interface VerificationResult {
4
+ ok: boolean;
5
+ digest?: Hex;
6
+ recovered?: `0x${string}`;
7
+ error?: string;
8
+ }
9
+ export declare function verifyClaimAttestationEnvelope(domain: Eip712DomainInput, message: ClaimAttestationMessage, signature: Hex): Promise<VerificationResult>;
10
+ export declare function verifyIntentAttestationEnvelope(domain: Eip712DomainInput, message: IntentAttestationMessage, signature: Hex): Promise<VerificationResult>;
11
+ export declare function reachedThreshold(validCount: number, threshold: number): boolean;
@@ -0,0 +1,60 @@
1
+ import { claimAttestationDigest, intentAttestationDigest, recoverClaimAttester, recoverIntentAttester } from "./eip712.js";
2
+ import { assertNotExpired } from "./attestation.js";
3
+ async function verifyEnvelope(verifier, computeDigest, recoverAddress) {
4
+ try {
5
+ const digest = computeDigest();
6
+ const recovered = await recoverAddress();
7
+ if (recovered.toLowerCase() !== verifier.toLowerCase()) {
8
+ return {
9
+ ok: false,
10
+ digest,
11
+ recovered,
12
+ error: "signature does not recover claimed verifier"
13
+ };
14
+ }
15
+ return {
16
+ ok: true,
17
+ digest,
18
+ recovered
19
+ };
20
+ }
21
+ catch (error) {
22
+ return {
23
+ ok: false,
24
+ error: error instanceof Error ? error.message : String(error)
25
+ };
26
+ }
27
+ }
28
+ export async function verifyClaimAttestationEnvelope(domain, message, signature) {
29
+ try {
30
+ assertNotExpired(message.expiresAt);
31
+ }
32
+ catch (error) {
33
+ return {
34
+ ok: false,
35
+ error: error instanceof Error ? error.message : String(error)
36
+ };
37
+ }
38
+ return verifyEnvelope(message.verifier, () => claimAttestationDigest(domain, message), () => recoverClaimAttester(domain, message, signature));
39
+ }
40
+ export async function verifyIntentAttestationEnvelope(domain, message, signature) {
41
+ try {
42
+ assertNotExpired(message.expiresAt);
43
+ }
44
+ catch (error) {
45
+ return {
46
+ ok: false,
47
+ error: error instanceof Error ? error.message : String(error)
48
+ };
49
+ }
50
+ return verifyEnvelope(message.verifier, () => intentAttestationDigest(domain, message), () => recoverIntentAttester(domain, message, signature));
51
+ }
52
+ export function reachedThreshold(validCount, threshold) {
53
+ if (!Number.isInteger(validCount) || validCount < 0) {
54
+ throw new Error("validCount must be a non-negative integer");
55
+ }
56
+ if (!Number.isInteger(threshold) || threshold <= 0) {
57
+ throw new Error("threshold must be a positive integer");
58
+ }
59
+ return validCount >= threshold;
60
+ }
@@ -0,0 +1,4 @@
1
+ export declare function unixNow(): bigint;
2
+ export declare function isExpired(expiresAt: bigint, now?: bigint): boolean;
3
+ export declare function assertNotExpired(expiresAt: bigint, now?: bigint): void;
4
+ export declare function assertNonceStrictlyIncreases(lastNonce: bigint | null, incomingNonce: bigint): void;
@@ -0,0 +1,16 @@
1
+ export function unixNow() {
2
+ return BigInt(Math.floor(Date.now() / 1000));
3
+ }
4
+ export function isExpired(expiresAt, now = unixNow()) {
5
+ return expiresAt <= now;
6
+ }
7
+ export function assertNotExpired(expiresAt, now = unixNow()) {
8
+ if (isExpired(expiresAt, now)) {
9
+ throw new Error(`signature expired: expiresAt=${expiresAt.toString(10)}, now=${now.toString(10)}`);
10
+ }
11
+ }
12
+ export function assertNonceStrictlyIncreases(lastNonce, incomingNonce) {
13
+ if (lastNonce !== null && incomingNonce <= lastNonce) {
14
+ throw new Error(`nonce must strictly increase: last=${lastNonce.toString(10)}, incoming=${incomingNonce.toString(10)}`);
15
+ }
16
+ }
@@ -0,0 +1,3 @@
1
+ import type { ClaimPayload, TradeIntent } from "./types.js";
2
+ export declare function canonicalClaim(input: ClaimPayload): ClaimPayload;
3
+ export declare function canonicalIntent(input: TradeIntent): TradeIntent;
@@ -0,0 +1,37 @@
1
+ import { getAddress } from "viem";
2
+ function normalizeText(value) {
3
+ return value.normalize("NFC").trim();
4
+ }
5
+ function normalizeAddress(value) {
6
+ return getAddress(value);
7
+ }
8
+ export function canonicalClaim(input) {
9
+ return {
10
+ ...input,
11
+ schemaId: normalizeText(input.schemaId),
12
+ sourceType: normalizeText(input.sourceType),
13
+ sourceRef: normalizeText(input.sourceRef),
14
+ selector: normalizeText(input.selector),
15
+ extracted: normalizeText(input.extracted),
16
+ extractedType: normalizeText(input.extractedType),
17
+ evidenceType: normalizeText(input.evidenceType),
18
+ evidenceURI: normalizeText(input.evidenceURI),
19
+ crawler: normalizeAddress(input.crawler),
20
+ notes: input.notes === undefined ? undefined : normalizeText(input.notes)
21
+ };
22
+ }
23
+ export function canonicalIntent(input) {
24
+ const normalizedAction = normalizeText(input.action).toUpperCase();
25
+ if (normalizedAction !== "BUY" && normalizedAction !== "SELL") {
26
+ throw new Error(`invalid action: ${input.action}`);
27
+ }
28
+ return {
29
+ ...input,
30
+ intentVersion: normalizeText(input.intentVersion),
31
+ vault: normalizeAddress(input.vault),
32
+ action: normalizedAction,
33
+ tokenIn: normalizeAddress(input.tokenIn),
34
+ tokenOut: normalizeAddress(input.tokenOut),
35
+ reason: input.reason === undefined ? undefined : normalizeText(input.reason)
36
+ };
37
+ }
@@ -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>;
@@ -0,0 +1,74 @@
1
+ import { hashTypedData, recoverTypedDataAddress, verifyTypedData } from "viem";
2
+ export const CLAIM_ATTESTATION_TYPES = {
3
+ ClaimAttestation: [
4
+ { name: "claimHash", type: "bytes32" },
5
+ { name: "epochId", type: "uint64" },
6
+ { name: "verifier", type: "address" },
7
+ { name: "expiresAt", type: "uint64" },
8
+ { name: "nonce", type: "uint256" }
9
+ ]
10
+ };
11
+ export const INTENT_ATTESTATION_TYPES = {
12
+ IntentAttestation: [
13
+ { name: "intentHash", type: "bytes32" },
14
+ { name: "verifier", type: "address" },
15
+ { name: "expiresAt", type: "uint64" },
16
+ { name: "nonce", type: "uint256" }
17
+ ]
18
+ };
19
+ export function toEip712Domain(input) {
20
+ return {
21
+ name: input.name,
22
+ version: input.version,
23
+ chainId: input.chainId,
24
+ verifyingContract: input.verifyingContract
25
+ };
26
+ }
27
+ export function claimAttestationTypedData(domain, message) {
28
+ return {
29
+ domain: toEip712Domain(domain),
30
+ types: CLAIM_ATTESTATION_TYPES,
31
+ primaryType: "ClaimAttestation",
32
+ message
33
+ };
34
+ }
35
+ export function intentAttestationTypedData(domain, message) {
36
+ return {
37
+ domain: toEip712Domain(domain),
38
+ types: INTENT_ATTESTATION_TYPES,
39
+ primaryType: "IntentAttestation",
40
+ message
41
+ };
42
+ }
43
+ export function claimAttestationDigest(domain, message) {
44
+ return hashTypedData(claimAttestationTypedData(domain, message));
45
+ }
46
+ export function intentAttestationDigest(domain, message) {
47
+ return hashTypedData(intentAttestationTypedData(domain, message));
48
+ }
49
+ export async function verifyClaimAttestation(domain, message, signature) {
50
+ return verifyTypedData({
51
+ ...claimAttestationTypedData(domain, message),
52
+ address: message.verifier,
53
+ signature
54
+ });
55
+ }
56
+ export async function verifyIntentAttestation(domain, message, signature) {
57
+ return verifyTypedData({
58
+ ...intentAttestationTypedData(domain, message),
59
+ address: message.verifier,
60
+ signature
61
+ });
62
+ }
63
+ export async function recoverClaimAttester(domain, message, signature) {
64
+ return recoverTypedDataAddress({
65
+ ...claimAttestationTypedData(domain, message),
66
+ signature
67
+ });
68
+ }
69
+ export async function recoverIntentAttester(domain, message, signature) {
70
+ return recoverTypedDataAddress({
71
+ ...intentAttestationTypedData(domain, message),
72
+ signature
73
+ });
74
+ }
@@ -0,0 +1,4 @@
1
+ import type { Hex } from "./types.js";
2
+ export declare const ERC1271_MAGIC_VALUE = "0x1626ba7e";
3
+ export declare function encodeErc1271IsValidSignatureCall(hash: Hex, signature: Hex): Hex;
4
+ export declare function isValidErc1271Result(result: Hex): boolean;
@@ -0,0 +1,24 @@
1
+ import { encodeFunctionData } from "viem";
2
+ export const ERC1271_MAGIC_VALUE = "0x1626ba7e";
3
+ const ERC1271_ABI = [
4
+ {
5
+ type: "function",
6
+ name: "isValidSignature",
7
+ stateMutability: "view",
8
+ inputs: [
9
+ { name: "hash", type: "bytes32" },
10
+ { name: "signature", type: "bytes" }
11
+ ],
12
+ outputs: [{ name: "magicValue", type: "bytes4" }]
13
+ }
14
+ ];
15
+ export function encodeErc1271IsValidSignatureCall(hash, signature) {
16
+ return encodeFunctionData({
17
+ abi: ERC1271_ABI,
18
+ functionName: "isValidSignature",
19
+ args: [hash, signature]
20
+ });
21
+ }
22
+ export function isValidErc1271Result(result) {
23
+ return result.slice(0, 10).toLowerCase() === ERC1271_MAGIC_VALUE;
24
+ }
@@ -0,0 +1,3 @@
1
+ import type { Hex, NadfunExecutionDataV1 } from "./types.js";
2
+ export declare function encodeNadfunExecutionDataV1(data: NadfunExecutionDataV1): Hex;
3
+ export declare function decodeNadfunExecutionDataV1(raw: Hex): NadfunExecutionDataV1;
@@ -0,0 +1,66 @@
1
+ import { decodeAbiParameters, encodeAbiParameters, parseAbiParameters } from "viem";
2
+ import { assertUint64 } from "./validate.js";
3
+ const NADFUN_V1_ABI = parseAbiParameters("uint8 version,uint8 action,uint8 venue,address router,address recipient,address token,uint64 deadline,uint256 amountOutMin,bytes extra");
4
+ const ACTION_TO_ID = {
5
+ BUY: 1,
6
+ SELL: 2
7
+ };
8
+ const VENUE_TO_ID = {
9
+ NADFUN_BONDING_CURVE: 1,
10
+ NADFUN_DEX: 2
11
+ };
12
+ const ID_TO_ACTION = {
13
+ 1: "BUY",
14
+ 2: "SELL"
15
+ };
16
+ const ID_TO_VENUE = {
17
+ 1: "NADFUN_BONDING_CURVE",
18
+ 2: "NADFUN_DEX"
19
+ };
20
+ function assertVersion(version) {
21
+ if (version !== 1) {
22
+ throw new Error(`unsupported execution-data version: ${version}`);
23
+ }
24
+ }
25
+ function assertKnownAction(actionId) {
26
+ const action = ID_TO_ACTION[actionId];
27
+ if (!action)
28
+ throw new Error(`unsupported action id: ${actionId}`);
29
+ return action;
30
+ }
31
+ function assertKnownVenue(venueId) {
32
+ const venue = ID_TO_VENUE[venueId];
33
+ if (!venue)
34
+ throw new Error(`unsupported venue id: ${venueId}`);
35
+ return venue;
36
+ }
37
+ export function encodeNadfunExecutionDataV1(data) {
38
+ assertUint64(data.deadline, "deadline");
39
+ return encodeAbiParameters(NADFUN_V1_ABI, [
40
+ data.version,
41
+ ACTION_TO_ID[data.action],
42
+ VENUE_TO_ID[data.venue],
43
+ data.router,
44
+ data.recipient,
45
+ data.token,
46
+ data.deadline,
47
+ data.amountOutMin,
48
+ data.extra
49
+ ]);
50
+ }
51
+ export function decodeNadfunExecutionDataV1(raw) {
52
+ const [version, actionId, venueId, router, recipient, token, deadline, amountOutMin, extra] = decodeAbiParameters(NADFUN_V1_ABI, raw);
53
+ const v = Number(version);
54
+ assertVersion(v);
55
+ return {
56
+ version: 1,
57
+ action: assertKnownAction(Number(actionId)),
58
+ venue: assertKnownVenue(Number(venueId)),
59
+ router,
60
+ recipient,
61
+ token,
62
+ deadline,
63
+ amountOutMin,
64
+ extra
65
+ };
66
+ }
@@ -0,0 +1,16 @@
1
+ import type { Address, ClaimPayload, Hex, TradeIntent } from "./types.js";
2
+ export declare function claimHash(payload: ClaimPayload): Hex;
3
+ export declare function intentHash(intent: TradeIntent): Hex;
4
+ export declare function snapshotHash(epochId: bigint, orderedClaimHashes: Hex[]): Hex;
5
+ export declare function canonicalOrderedClaimHashes(claimHashes: Hex[]): Hex[];
6
+ export declare function snapshotHashFromUnordered(epochId: bigint, claimHashes: Hex[]): Hex;
7
+ export declare function reasonHash(reason: string): Hex;
8
+ /**
9
+ * Canonical allowlist hash for intent execution route.
10
+ * Must match ClawCore allowlist verification logic.
11
+ */
12
+ export declare function intentExecutionAllowlistHash(tokenIn: Address, tokenOut: Address, quoteAmountOut: bigint, minAmountOut: bigint, adapter: Address, adapterDataHash: Hex): Hex;
13
+ /**
14
+ * Helper that hashes raw adapter calldata before building the allowlist hash.
15
+ */
16
+ export declare function intentExecutionCallHash(tokenIn: Address, tokenOut: Address, quoteAmountOut: bigint, minAmountOut: bigint, adapter: Address, adapterData: Hex): Hex;