@heyanon-arp/sdk 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +147 -0
- package/dist/assets.d.ts +101 -0
- package/dist/attestation/attestation.d.ts +29 -0
- package/dist/attestation/index.d.ts +2 -0
- package/dist/attestation/scrypt-proof.d.ts +28 -0
- package/dist/canonical/canonicalize.d.ts +33 -0
- package/dist/canonical/index.d.ts +1 -0
- package/dist/challenge/challenge.d.ts +11 -0
- package/dist/challenge/index.d.ts +1 -0
- package/dist/cosignature/cosign.d.ts +35 -0
- package/dist/cosignature/index.d.ts +2 -0
- package/dist/did/document.d.ts +30 -0
- package/dist/did/format.d.ts +23 -0
- package/dist/did/index.d.ts +2 -0
- package/dist/envelope/index.d.ts +4 -0
- package/dist/envelope/sign.d.ts +28 -0
- package/dist/envelope/verify.d.ts +37 -0
- package/dist/escrow/caip19.d.ts +41 -0
- package/dist/escrow/condition-hash.d.ts +79 -0
- package/dist/escrow/create-lock.d.ts +39 -0
- package/dist/escrow/index.d.ts +4 -0
- package/dist/escrow/lock-id.d.ts +67 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +853 -0
- package/dist/index.mjs +761 -0
- package/dist/keys/base58btc.d.ts +10 -0
- package/dist/keys/ed25519.d.ts +33 -0
- package/dist/keys/index.d.ts +3 -0
- package/dist/purpose.d.ts +52 -0
- package/dist/server-chain/chain.d.ts +52 -0
- package/dist/server-chain/index.d.ts +2 -0
- package/dist/settlement/index.d.ts +4 -0
- package/dist/settlement/settlement.d.ts +111 -0
- package/dist/settlement/token-program.d.ts +72 -0
- package/dist/types/body.d.ts +263 -0
- package/dist/types/envelope.d.ts +121 -0
- package/dist/types/identity.d.ts +62 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/nonce.d.ts +9 -0
- package/dist/utils/timestamp.d.ts +17 -0
- package/dist/utils/uuid.d.ts +10 -0
- package/dist/webhook/index.d.ts +2 -0
- package/dist/webhook/webhook.d.ts +38 -0
- package/package.json +58 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { PurposeValue } from '../purpose';
|
|
2
|
+
/**
|
|
3
|
+
* Wire-level types per [00-core/protocol.md](../../../00-core/protocol.md)
|
|
4
|
+
* and [00-core/schemas.md](../../../00-core/schemas.md).
|
|
5
|
+
*
|
|
6
|
+
* Body-type-specific shapes (handshake / contract / delegation / receipt
|
|
7
|
+
* / etc.) live alongside their handlers in the consumer code — keeping
|
|
8
|
+
* them out of this file avoids the SDK becoming a kitchen-sink of every
|
|
9
|
+
* message type. A consumer who needs typed bodies can extend `Envelope<T>`
|
|
10
|
+
* with their own `T extends Body`.
|
|
11
|
+
*/
|
|
12
|
+
/** Hash string in protocol format `sha256:<64-char hex>`. */
|
|
13
|
+
export type Sha256Hex = `sha256:${string}`;
|
|
14
|
+
/** Ed25519 signature in protocol format `ed25519:<base64>`. */
|
|
15
|
+
export type Ed25519Sig = `ed25519:${string}`;
|
|
16
|
+
/** DID format `did:arp:<base58btc>`. */
|
|
17
|
+
export type Did = `did:arp:${string}`;
|
|
18
|
+
/**
|
|
19
|
+
* Client-signed `protected` block. All fields here are part of the
|
|
20
|
+
* signing input. Server-assigned chain fields (`relationship_event_index`,
|
|
21
|
+
* `prev_server_event_hash`) live OUTSIDE this block — clients MUST NOT
|
|
22
|
+
* sign them.
|
|
23
|
+
*/
|
|
24
|
+
export interface ProtectedBlock {
|
|
25
|
+
protocol_version: 'arp/0.1';
|
|
26
|
+
purpose: PurposeValue;
|
|
27
|
+
message_id: string;
|
|
28
|
+
sender_did: Did;
|
|
29
|
+
recipient_did: Did;
|
|
30
|
+
/** UUID v4; null only on the first handshake. */
|
|
31
|
+
relationship_id: string | null;
|
|
32
|
+
sender_sequence: number;
|
|
33
|
+
sender_nonce: string;
|
|
34
|
+
timestamp: string;
|
|
35
|
+
expires_at: string;
|
|
36
|
+
body_hash: Sha256Hex;
|
|
37
|
+
attachments_hash: Sha256Hex | null;
|
|
38
|
+
delivery_id: string | null;
|
|
39
|
+
}
|
|
40
|
+
/** Body shape — `type` discriminator + per-type `content`. */
|
|
41
|
+
export interface Body<TContent = Record<string, unknown>> {
|
|
42
|
+
type: string;
|
|
43
|
+
content: TContent;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Optional attachments. Three top-level fields are SDK-aware:
|
|
47
|
+
* `co_signature` (semantic intent), `settlement_signatures`
|
|
48
|
+
* (financial authorisation), and `escrow_lock` (`delegation.offer`
|
|
49
|
+
* carries a pre-signed `create_lock` Solana tx). Other body-specific
|
|
50
|
+
* attachments live under their own keys and are passed through
|
|
51
|
+
* opaquely.
|
|
52
|
+
*/
|
|
53
|
+
export interface Attachments {
|
|
54
|
+
co_signature?: CoSignature;
|
|
55
|
+
settlement_signatures?: SettlementSignatures;
|
|
56
|
+
escrow_lock?: EscrowLockAttachment;
|
|
57
|
+
[other: string]: unknown;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Attached by `delegation.offer` envelopes when the payer (the offer
|
|
61
|
+
* sender) wants to fund the lock as part of the same envelope.
|
|
62
|
+
*
|
|
63
|
+
* - `signed_tx_blob` is the base64-encoded full Solana tx with the
|
|
64
|
+
* payer's settlement key already a tx-level signer.
|
|
65
|
+
* - `lock_id` is the deterministic-from-delegation_id hex32, used
|
|
66
|
+
* for the server's idempotency-key check (server independently
|
|
67
|
+
* derives the same id via `deriveLockId`).
|
|
68
|
+
* - `amount` is the base-unit amount (decimal-as-string); must
|
|
69
|
+
* equal `toBaseUnits(body.content.amount, currency.decimals)`.
|
|
70
|
+
* - `asset_id` is the CAIP-19 currency the lock holds; must equal
|
|
71
|
+
* `body.content.currency.asset_id` (defence-in-depth).
|
|
72
|
+
* - `expiry` is the on-chain unix-seconds expiry; must satisfy the
|
|
73
|
+
* contract's MIN/MAX windows AND the spec's
|
|
74
|
+
* `deadline + DISPUTE_BUFFER` constraint.
|
|
75
|
+
*
|
|
76
|
+
* Server validation in `EnvelopeValidator` decodes the tx blob via
|
|
77
|
+
* Anchor IDL and cross-checks every field against the envelope body.
|
|
78
|
+
*/
|
|
79
|
+
export interface EscrowLockAttachment {
|
|
80
|
+
signed_tx_blob: string;
|
|
81
|
+
lock_id: string;
|
|
82
|
+
amount: string;
|
|
83
|
+
asset_id: string;
|
|
84
|
+
expiry: number;
|
|
85
|
+
}
|
|
86
|
+
export interface CoSignature {
|
|
87
|
+
agent_did: Did;
|
|
88
|
+
purpose: PurposeValue;
|
|
89
|
+
payload_hash: Sha256Hex;
|
|
90
|
+
sig: Ed25519Sig;
|
|
91
|
+
}
|
|
92
|
+
export interface SettlementSignatures {
|
|
93
|
+
purpose: PurposeValue;
|
|
94
|
+
payer: SettlementParty;
|
|
95
|
+
payee: SettlementParty;
|
|
96
|
+
expires_at: number;
|
|
97
|
+
}
|
|
98
|
+
export interface SettlementParty {
|
|
99
|
+
settlement_pubkey: string;
|
|
100
|
+
sig: Ed25519Sig;
|
|
101
|
+
}
|
|
102
|
+
/** Top-level envelope as it appears on the wire. */
|
|
103
|
+
export interface Envelope<TBody extends Body = Body> {
|
|
104
|
+
protected: ProtectedBlock;
|
|
105
|
+
body: TBody;
|
|
106
|
+
attachments?: Attachments;
|
|
107
|
+
sender_signature: Ed25519Sig;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Server-side projection of an accepted event. Adds chain fields
|
|
111
|
+
* (server-assigned, NOT in signing input). Returned by the ingestion
|
|
112
|
+
* endpoint and persisted on the events table.
|
|
113
|
+
*/
|
|
114
|
+
export interface PersistedEvent<TBody extends Body = Body> extends Envelope<TBody> {
|
|
115
|
+
event_id: string;
|
|
116
|
+
relationship_event_index: number;
|
|
117
|
+
prev_server_event_hash: string | null;
|
|
118
|
+
server_event_hash: string;
|
|
119
|
+
signed_message_hash: string;
|
|
120
|
+
server_timestamp: string;
|
|
121
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { KeyMode } from '../did';
|
|
2
|
+
import type { Did } from './envelope';
|
|
3
|
+
/**
|
|
4
|
+
* Owner attestation methods per [00-core/identity.md](../../../00-core/identity.md).
|
|
5
|
+
*
|
|
6
|
+
* V1 ships `scrypt_password_proof` only; the others are reserved
|
|
7
|
+
* placeholders for forward-compat (V1.5 / V2).
|
|
8
|
+
*/
|
|
9
|
+
export type OwnerSigningMethod = 'scrypt_password_proof' | 'ed25519_owner_key' | 'totp+passphrase';
|
|
10
|
+
/**
|
|
11
|
+
* `ARP-KEY-LINK-v1` payload — the canonical-JSON-hashed object an owner
|
|
12
|
+
* signs at registration. Carries the link between identity and settlement
|
|
13
|
+
* keys plus owner identity / method metadata.
|
|
14
|
+
*/
|
|
15
|
+
export interface KeyLinkPayload {
|
|
16
|
+
purpose: 'ARP-KEY-LINK-v1';
|
|
17
|
+
agent_did: Did;
|
|
18
|
+
identity_public_key: string;
|
|
19
|
+
settlement_public_key: string;
|
|
20
|
+
key_mode: KeyMode;
|
|
21
|
+
owner_id: string;
|
|
22
|
+
owner_signing_method: OwnerSigningMethod;
|
|
23
|
+
link_method: 'manual' | 'imported' | 'derived_bip39';
|
|
24
|
+
created_at: string;
|
|
25
|
+
nonce: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* `ARP-KEY-ROTATION-v1` payload — separate purpose from KEY-LINK
|
|
29
|
+
* because rotation breaks the `agent_did = base58btc(identity_pubkey)`
|
|
30
|
+
* invariant. Agent DID stays frozen; identity_public_key changes.
|
|
31
|
+
*/
|
|
32
|
+
export interface KeyRotationPayload {
|
|
33
|
+
purpose: 'ARP-KEY-ROTATION-v1';
|
|
34
|
+
agent_did: Did;
|
|
35
|
+
current_identity_public_key: string;
|
|
36
|
+
new_identity_public_key: string;
|
|
37
|
+
settlement_public_key: string;
|
|
38
|
+
supersedes_attestation_id: string;
|
|
39
|
+
owner_id: string;
|
|
40
|
+
owner_signing_method: OwnerSigningMethod;
|
|
41
|
+
rotation_reason: 'scheduled' | 'compromise' | 'lost_device' | 'other';
|
|
42
|
+
created_at: string;
|
|
43
|
+
nonce: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* `scrypt_password_proof` — the V1 owner attestation envelope. The
|
|
47
|
+
* signature is HMAC-SHA256(scrypt(password, salt), sha256(canonical(payload))),
|
|
48
|
+
* base64-encoded. NOT an Ed25519 signature; verification is
|
|
49
|
+
* server-side via the stored scrypt-derived key.
|
|
50
|
+
*/
|
|
51
|
+
export interface ScryptPasswordAttestation<TPayload extends KeyLinkPayload | KeyRotationPayload = KeyLinkPayload> {
|
|
52
|
+
payload: TPayload;
|
|
53
|
+
sig: string;
|
|
54
|
+
scrypt_salt_id: string;
|
|
55
|
+
}
|
|
56
|
+
/** Standard scrypt parameters used for owner password proofs (V1). */
|
|
57
|
+
export declare const SCRYPT_PARAMS: {
|
|
58
|
+
readonly N: 32768;
|
|
59
|
+
readonly r: 8;
|
|
60
|
+
readonly p: 1;
|
|
61
|
+
readonly dkLen: 32;
|
|
62
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { Sha256Hex, Ed25519Sig, Did, ProtectedBlock, Body, Attachments, CoSignature, SettlementSignatures, SettlementParty, EscrowLockAttachment, Envelope, PersistedEvent, } from './envelope';
|
|
2
|
+
export type { HandshakeBody, HandshakeContent, HandshakeResponseBody, HandshakeResponseContent, ContractBody, ContractContent, DelegationBody, DelegationContent, WorkRequestBody, WorkRequestContent, WorkResponseBody, WorkResponseContent, ReceiptBody, ReceiptContent, MemoryDeltaBody, MemoryDeltaContent, DisputeBody, DisputeContent, AnyBody, ReceiptCosignPayload, DisputeResponseCosignPayload, CosignPayload, DeclineReason, AssetIdentifier, } from './body';
|
|
3
|
+
export { DECLINE_REASONS, isDeclineReason } from './body';
|
|
4
|
+
export type { OwnerSigningMethod, KeyLinkPayload, KeyRotationPayload, ScryptPasswordAttestation } from './identity';
|
|
5
|
+
export { SCRYPT_PARAMS } from './identity';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a 16-byte random nonce, base64url-encoded without padding.
|
|
3
|
+
*
|
|
4
|
+
* Used in `protected.sender_nonce` and inside attestation payloads
|
|
5
|
+
* (`ARP-KEY-LINK-v1`, `ARP-KEY-ROTATION-v1`) to defend against
|
|
6
|
+
* accidental hash collisions and replay where two semantically
|
|
7
|
+
* distinct messages would otherwise hash to the same value.
|
|
8
|
+
*/
|
|
9
|
+
export declare function senderNonce(): string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a `Date` (or now) as RFC 3339 / ISO 8601 in UTC with second
|
|
3
|
+
* precision — matches `protected.timestamp` and `protected.expires_at`
|
|
4
|
+
* format expected by the protocol verifier.
|
|
5
|
+
*
|
|
6
|
+
* Intentional choices:
|
|
7
|
+
* - second precision (no `.SSS` milliseconds), matching how server
|
|
8
|
+
* timestamps render in audit logs / state machines
|
|
9
|
+
* - explicit `Z` suffix for UTC, no offset notation
|
|
10
|
+
*/
|
|
11
|
+
export declare function rfc3339(at?: Date): string;
|
|
12
|
+
/**
|
|
13
|
+
* `expires_at` derived as `now + ttlSeconds`. The protocol caps
|
|
14
|
+
* envelope validity at 24 hours; callers who pass a longer TTL get
|
|
15
|
+
* a hard error rather than a silently-truncated value.
|
|
16
|
+
*/
|
|
17
|
+
export declare function expiresAt(ttlSeconds: number, now?: Date): string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC 4122 UUID v4 generator.
|
|
3
|
+
*
|
|
4
|
+
* The protocol uses UUIDv4 for `message_id`, `relationship_id`,
|
|
5
|
+
* `challenge_id`, etc. Implemented locally rather than via
|
|
6
|
+
* `crypto.randomUUID()` so the SDK stays portable across environments
|
|
7
|
+
* that don't expose the global `crypto` (older runtimes, WebWorkers
|
|
8
|
+
* without crypto polyfills).
|
|
9
|
+
*/
|
|
10
|
+
export declare function uuidV4(): string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ARP-WEBHOOK-v1` HMAC over the canonical webhook envelope. Used by
|
|
3
|
+
* the OutboxDeliveryWorker for the `X-ARP-Signature` header.
|
|
4
|
+
*
|
|
5
|
+
* Inputs (per backend's outbox spec):
|
|
6
|
+
* - delivery_id — outbox row id
|
|
7
|
+
* - recipient_did
|
|
8
|
+
* - envelope_message_id — envelope being delivered
|
|
9
|
+
* - server_event_hash — chain head at delivery time
|
|
10
|
+
* - attempt_n — 1-based retry counter
|
|
11
|
+
* - served_at — RFC3339, when this attempt was generated
|
|
12
|
+
*
|
|
13
|
+
* Each retry produces a different MAC because `attempt_n` and
|
|
14
|
+
* `served_at` participate in canonical input — replays of an old
|
|
15
|
+
* header on a fresh attempt fail HMAC verification.
|
|
16
|
+
*/
|
|
17
|
+
export interface WebhookSignableInput {
|
|
18
|
+
delivery_id: string;
|
|
19
|
+
recipient_did: string;
|
|
20
|
+
envelope_message_id: string;
|
|
21
|
+
server_event_hash: string;
|
|
22
|
+
attempt_n: number;
|
|
23
|
+
served_at: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Compute `X-ARP-Signature` value: `<purpose>=<base64(HMAC-SHA256(secret, sha256(canonical_json(input))))>`.
|
|
27
|
+
*
|
|
28
|
+
* Recipients lookup their per-sender shared secret, recompute the
|
|
29
|
+
* HMAC over the same canonical input, and compare against the
|
|
30
|
+
* received header.
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildWebhookSignatureHeader(input: WebhookSignableInput, sharedSecret: Uint8Array): string;
|
|
33
|
+
/**
|
|
34
|
+
* Constant-time compare an inbound `X-ARP-Signature` header against
|
|
35
|
+
* the expected one. Returns `false` on shape mismatch, missing
|
|
36
|
+
* purpose label, or HMAC mismatch — never throws.
|
|
37
|
+
*/
|
|
38
|
+
export declare function verifyWebhookSignatureHeader(headerValue: string, input: WebhookSignableInput, sharedSecret: Uint8Array): boolean;
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@heyanon-arp/sdk",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "TypeScript SDK for the Agent Relationship Protocol — canonical JSON, Ed25519 envelope sign/verify, did:arp identity, receipt co-signatures, scrypt key attestation, chain-audit helpers.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"arp",
|
|
8
|
+
"agent-relationship-protocol",
|
|
9
|
+
"did",
|
|
10
|
+
"ed25519",
|
|
11
|
+
"jcs",
|
|
12
|
+
"canonical-json",
|
|
13
|
+
"envelope",
|
|
14
|
+
"cosignature",
|
|
15
|
+
"a2a"
|
|
16
|
+
],
|
|
17
|
+
"main": "dist/index.js",
|
|
18
|
+
"module": "dist/index.mjs",
|
|
19
|
+
"types": "dist/index.d.ts",
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"import": "./dist/index.mjs",
|
|
27
|
+
"require": "./dist/index.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"LICENSE",
|
|
33
|
+
"README.md"
|
|
34
|
+
],
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=22"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@noble/ed25519": "^2.1.0",
|
|
40
|
+
"@noble/hashes": "^1.5.0",
|
|
41
|
+
"@scure/base": "^1.1.9",
|
|
42
|
+
"canonicalize": "^2.0.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "^22.10.7",
|
|
46
|
+
"tslib": "^2.6.2",
|
|
47
|
+
"tsup": "^8.3.5",
|
|
48
|
+
"typescript": "^5.5.4",
|
|
49
|
+
"vitest": "^2.1.8"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "tsup",
|
|
53
|
+
"start": "tsup --watch",
|
|
54
|
+
"test": "vitest --run",
|
|
55
|
+
"test:watch": "vitest",
|
|
56
|
+
"lint": "biome check . --write"
|
|
57
|
+
}
|
|
58
|
+
}
|