@t2000/sdk 5.16.0 → 5.18.0
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/dist/index.cjs +212 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -1
- package/dist/index.d.ts +50 -1
- package/dist/index.js +212 -3
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/dist/index.d.cts
CHANGED
|
@@ -62,6 +62,52 @@ declare function listModels(opts?: {
|
|
|
62
62
|
apiBase?: string;
|
|
63
63
|
}): Promise<ApiModel[]>;
|
|
64
64
|
|
|
65
|
+
type CheckStatus = 'pass' | 'fail' | 'skip';
|
|
66
|
+
type TrustMode = 'trustless' | 'receipt-asserted' | 'roadmap';
|
|
67
|
+
interface VerifyCheck {
|
|
68
|
+
name: string;
|
|
69
|
+
status: CheckStatus;
|
|
70
|
+
detail: string;
|
|
71
|
+
trust: TrustMode;
|
|
72
|
+
}
|
|
73
|
+
interface VerifyAnchor {
|
|
74
|
+
txDigest: string;
|
|
75
|
+
anchoredAtMs?: string;
|
|
76
|
+
anchoredBy?: string;
|
|
77
|
+
explorer: string;
|
|
78
|
+
}
|
|
79
|
+
interface VerifyResult {
|
|
80
|
+
receiptId: string;
|
|
81
|
+
/** True iff the receipt resolved AND its on-chain Sui anchor matches. */
|
|
82
|
+
verified: boolean;
|
|
83
|
+
/** The trustless core: an on-chain ReceiptAnchored event matches the receipt. */
|
|
84
|
+
anchorVerified: boolean;
|
|
85
|
+
checks: VerifyCheck[];
|
|
86
|
+
wireHash?: string;
|
|
87
|
+
workloadId?: string;
|
|
88
|
+
upstream?: {
|
|
89
|
+
provider?: string;
|
|
90
|
+
result?: string;
|
|
91
|
+
tcbStatus?: string;
|
|
92
|
+
};
|
|
93
|
+
anchor?: VerifyAnchor;
|
|
94
|
+
}
|
|
95
|
+
interface VerifyOptions {
|
|
96
|
+
/** Override the API base (default `api.t2000.ai/v1`). */
|
|
97
|
+
apiBase?: string;
|
|
98
|
+
/** Sui network for the trustless anchor read (default `mainnet`). */
|
|
99
|
+
network?: 'mainnet' | 'testnet';
|
|
100
|
+
/** Confidential model id for fetching the attested receipt-signing key
|
|
101
|
+
* (default `phala/glm-5.2`; the gateway key is workload-wide). */
|
|
102
|
+
model?: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Verify a confidential response by its receipt id. Reads the signed receipt
|
|
106
|
+
* (public), its on-chain Sui anchor (trustless), and reports a per-check result
|
|
107
|
+
* that FAILS CLOSED on any forgery or mismatch.
|
|
108
|
+
*/
|
|
109
|
+
declare function verifyReceipt(receiptId: string, opts?: VerifyOptions): Promise<VerifyResult>;
|
|
110
|
+
|
|
65
111
|
interface LimitsConfig {
|
|
66
112
|
/** Caps any single outbound write (send | swap | pay) by USD value. */
|
|
67
113
|
perTxUsd?: number;
|
|
@@ -225,6 +271,9 @@ declare class T2000 extends EventEmitter<T2000Events> {
|
|
|
225
271
|
apiKey?: string;
|
|
226
272
|
apiBase?: string;
|
|
227
273
|
}): Promise<ApiModel[]>;
|
|
274
|
+
/** Verify a confidential response by receipt id — checks the signed receipt
|
|
275
|
+
* + its trustless on-chain Sui anchor. Fails closed on any mismatch. */
|
|
276
|
+
verify(receiptId: string, opts?: VerifyOptions): Promise<VerifyResult>;
|
|
228
277
|
swap(params: {
|
|
229
278
|
from: string;
|
|
230
279
|
to: string;
|
|
@@ -1021,4 +1070,4 @@ declare function fullHandle(label: string, parentName?: string): string;
|
|
|
1021
1070
|
*/
|
|
1022
1071
|
declare function displayHandle(label: string, parentName?: string): string;
|
|
1023
1072
|
|
|
1024
|
-
export { AGENT_ID_PARENT, AGENT_ID_PARENT_NAME, AGENT_ID_PARENT_NFT_ID, AUDRIC_PARENT, AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, type ApiModel, type AppenderContext, BalanceResponse, type BuildAddLeafParams, type BuildRevokeLeafParams, type ChatMessage, type ChatParams, type ChatResult, type ChatUsage, type ComposeTxOptions, type ComposeTxResult, DEFAULT_API_BASE, type DailySpend, DepositInfo, InvalidAddressError, type LabelValidationResult, type LimitAssertInput, LimitEnforcer, LimitExceededError, type LimitKind, type LimitOperation, type LimitsConfig, type LimitsFile, type NormalizedAddress, OverlayFeeConfig, PayOptions, PayResult, PaymentRequest, SPONSORED_PYTH_DEPENDENT_PROVIDERS, SUINS_NAME_REGEX, SUI_ADDRESS_REGEX, SUI_ADDRESS_STRICT_REGEX, SendResult, type SendTransferInput, SendableAsset, type StepPreview, SuinsNotRegisteredError, type SuinsParent, SuinsRpcError, SupportedAsset, type SwapExecuteInput, SwapQuoteResult, SwapResult, SwapRouteResult, T2000, T2000Error, T2000Options, TransactionRecord, TransactionSigner, WRITE_APPENDER_REGISTRY, type WriteStep, type WriteToolName, ZkLoginProof, approxUsdValue, assertLimitConfig, buildAddLeafTx, buildRevokeLeafTx, chatCompletion, chatCompletionStream, clearLimits, composeTx, dailySpentToday, deriveAllowedAddressesFromPtb, displayHandle, exportPrivateKey, fullHandle, generateKeypair, getAddress, getLimits, getSponsoredSwapProviders, getSwapQuote, hasLimits, keypairFromPrivateKey, listModels, loadKey, looksLikeSuiNs, normalizeAddressInput, queryBalance, readLimitsFile, recordDailySpend, resolveAddressToSuinsViaRpc, resolveSuinsViaRpc, saveBech32, saveKey, setLimits, validateLabel, walletExists, writeLimitsFile };
|
|
1073
|
+
export { AGENT_ID_PARENT, AGENT_ID_PARENT_NAME, AGENT_ID_PARENT_NFT_ID, AUDRIC_PARENT, AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, type ApiModel, type AppenderContext, BalanceResponse, type BuildAddLeafParams, type BuildRevokeLeafParams, type ChatMessage, type ChatParams, type ChatResult, type ChatUsage, type CheckStatus, type ComposeTxOptions, type ComposeTxResult, DEFAULT_API_BASE, type DailySpend, DepositInfo, InvalidAddressError, type LabelValidationResult, type LimitAssertInput, LimitEnforcer, LimitExceededError, type LimitKind, type LimitOperation, type LimitsConfig, type LimitsFile, type NormalizedAddress, OverlayFeeConfig, PayOptions, PayResult, PaymentRequest, SPONSORED_PYTH_DEPENDENT_PROVIDERS, SUINS_NAME_REGEX, SUI_ADDRESS_REGEX, SUI_ADDRESS_STRICT_REGEX, SendResult, type SendTransferInput, SendableAsset, type StepPreview, SuinsNotRegisteredError, type SuinsParent, SuinsRpcError, SupportedAsset, type SwapExecuteInput, SwapQuoteResult, SwapResult, SwapRouteResult, T2000, T2000Error, T2000Options, TransactionRecord, TransactionSigner, type TrustMode, type VerifyAnchor, type VerifyCheck, type VerifyOptions, type VerifyResult, WRITE_APPENDER_REGISTRY, type WriteStep, type WriteToolName, ZkLoginProof, approxUsdValue, assertLimitConfig, buildAddLeafTx, buildRevokeLeafTx, chatCompletion, chatCompletionStream, clearLimits, composeTx, dailySpentToday, deriveAllowedAddressesFromPtb, displayHandle, exportPrivateKey, fullHandle, generateKeypair, getAddress, getLimits, getSponsoredSwapProviders, getSwapQuote, hasLimits, keypairFromPrivateKey, listModels, loadKey, looksLikeSuiNs, normalizeAddressInput, queryBalance, readLimitsFile, recordDailySpend, resolveAddressToSuinsViaRpc, resolveSuinsViaRpc, saveBech32, saveKey, setLimits, validateLabel, verifyReceipt, walletExists, writeLimitsFile };
|
package/dist/index.d.ts
CHANGED
|
@@ -62,6 +62,52 @@ declare function listModels(opts?: {
|
|
|
62
62
|
apiBase?: string;
|
|
63
63
|
}): Promise<ApiModel[]>;
|
|
64
64
|
|
|
65
|
+
type CheckStatus = 'pass' | 'fail' | 'skip';
|
|
66
|
+
type TrustMode = 'trustless' | 'receipt-asserted' | 'roadmap';
|
|
67
|
+
interface VerifyCheck {
|
|
68
|
+
name: string;
|
|
69
|
+
status: CheckStatus;
|
|
70
|
+
detail: string;
|
|
71
|
+
trust: TrustMode;
|
|
72
|
+
}
|
|
73
|
+
interface VerifyAnchor {
|
|
74
|
+
txDigest: string;
|
|
75
|
+
anchoredAtMs?: string;
|
|
76
|
+
anchoredBy?: string;
|
|
77
|
+
explorer: string;
|
|
78
|
+
}
|
|
79
|
+
interface VerifyResult {
|
|
80
|
+
receiptId: string;
|
|
81
|
+
/** True iff the receipt resolved AND its on-chain Sui anchor matches. */
|
|
82
|
+
verified: boolean;
|
|
83
|
+
/** The trustless core: an on-chain ReceiptAnchored event matches the receipt. */
|
|
84
|
+
anchorVerified: boolean;
|
|
85
|
+
checks: VerifyCheck[];
|
|
86
|
+
wireHash?: string;
|
|
87
|
+
workloadId?: string;
|
|
88
|
+
upstream?: {
|
|
89
|
+
provider?: string;
|
|
90
|
+
result?: string;
|
|
91
|
+
tcbStatus?: string;
|
|
92
|
+
};
|
|
93
|
+
anchor?: VerifyAnchor;
|
|
94
|
+
}
|
|
95
|
+
interface VerifyOptions {
|
|
96
|
+
/** Override the API base (default `api.t2000.ai/v1`). */
|
|
97
|
+
apiBase?: string;
|
|
98
|
+
/** Sui network for the trustless anchor read (default `mainnet`). */
|
|
99
|
+
network?: 'mainnet' | 'testnet';
|
|
100
|
+
/** Confidential model id for fetching the attested receipt-signing key
|
|
101
|
+
* (default `phala/glm-5.2`; the gateway key is workload-wide). */
|
|
102
|
+
model?: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Verify a confidential response by its receipt id. Reads the signed receipt
|
|
106
|
+
* (public), its on-chain Sui anchor (trustless), and reports a per-check result
|
|
107
|
+
* that FAILS CLOSED on any forgery or mismatch.
|
|
108
|
+
*/
|
|
109
|
+
declare function verifyReceipt(receiptId: string, opts?: VerifyOptions): Promise<VerifyResult>;
|
|
110
|
+
|
|
65
111
|
interface LimitsConfig {
|
|
66
112
|
/** Caps any single outbound write (send | swap | pay) by USD value. */
|
|
67
113
|
perTxUsd?: number;
|
|
@@ -225,6 +271,9 @@ declare class T2000 extends EventEmitter<T2000Events> {
|
|
|
225
271
|
apiKey?: string;
|
|
226
272
|
apiBase?: string;
|
|
227
273
|
}): Promise<ApiModel[]>;
|
|
274
|
+
/** Verify a confidential response by receipt id — checks the signed receipt
|
|
275
|
+
* + its trustless on-chain Sui anchor. Fails closed on any mismatch. */
|
|
276
|
+
verify(receiptId: string, opts?: VerifyOptions): Promise<VerifyResult>;
|
|
228
277
|
swap(params: {
|
|
229
278
|
from: string;
|
|
230
279
|
to: string;
|
|
@@ -1021,4 +1070,4 @@ declare function fullHandle(label: string, parentName?: string): string;
|
|
|
1021
1070
|
*/
|
|
1022
1071
|
declare function displayHandle(label: string, parentName?: string): string;
|
|
1023
1072
|
|
|
1024
|
-
export { AGENT_ID_PARENT, AGENT_ID_PARENT_NAME, AGENT_ID_PARENT_NFT_ID, AUDRIC_PARENT, AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, type ApiModel, type AppenderContext, BalanceResponse, type BuildAddLeafParams, type BuildRevokeLeafParams, type ChatMessage, type ChatParams, type ChatResult, type ChatUsage, type ComposeTxOptions, type ComposeTxResult, DEFAULT_API_BASE, type DailySpend, DepositInfo, InvalidAddressError, type LabelValidationResult, type LimitAssertInput, LimitEnforcer, LimitExceededError, type LimitKind, type LimitOperation, type LimitsConfig, type LimitsFile, type NormalizedAddress, OverlayFeeConfig, PayOptions, PayResult, PaymentRequest, SPONSORED_PYTH_DEPENDENT_PROVIDERS, SUINS_NAME_REGEX, SUI_ADDRESS_REGEX, SUI_ADDRESS_STRICT_REGEX, SendResult, type SendTransferInput, SendableAsset, type StepPreview, SuinsNotRegisteredError, type SuinsParent, SuinsRpcError, SupportedAsset, type SwapExecuteInput, SwapQuoteResult, SwapResult, SwapRouteResult, T2000, T2000Error, T2000Options, TransactionRecord, TransactionSigner, WRITE_APPENDER_REGISTRY, type WriteStep, type WriteToolName, ZkLoginProof, approxUsdValue, assertLimitConfig, buildAddLeafTx, buildRevokeLeafTx, chatCompletion, chatCompletionStream, clearLimits, composeTx, dailySpentToday, deriveAllowedAddressesFromPtb, displayHandle, exportPrivateKey, fullHandle, generateKeypair, getAddress, getLimits, getSponsoredSwapProviders, getSwapQuote, hasLimits, keypairFromPrivateKey, listModels, loadKey, looksLikeSuiNs, normalizeAddressInput, queryBalance, readLimitsFile, recordDailySpend, resolveAddressToSuinsViaRpc, resolveSuinsViaRpc, saveBech32, saveKey, setLimits, validateLabel, walletExists, writeLimitsFile };
|
|
1073
|
+
export { AGENT_ID_PARENT, AGENT_ID_PARENT_NAME, AGENT_ID_PARENT_NFT_ID, AUDRIC_PARENT, AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, type ApiModel, type AppenderContext, BalanceResponse, type BuildAddLeafParams, type BuildRevokeLeafParams, type ChatMessage, type ChatParams, type ChatResult, type ChatUsage, type CheckStatus, type ComposeTxOptions, type ComposeTxResult, DEFAULT_API_BASE, type DailySpend, DepositInfo, InvalidAddressError, type LabelValidationResult, type LimitAssertInput, LimitEnforcer, LimitExceededError, type LimitKind, type LimitOperation, type LimitsConfig, type LimitsFile, type NormalizedAddress, OverlayFeeConfig, PayOptions, PayResult, PaymentRequest, SPONSORED_PYTH_DEPENDENT_PROVIDERS, SUINS_NAME_REGEX, SUI_ADDRESS_REGEX, SUI_ADDRESS_STRICT_REGEX, SendResult, type SendTransferInput, SendableAsset, type StepPreview, SuinsNotRegisteredError, type SuinsParent, SuinsRpcError, SupportedAsset, type SwapExecuteInput, SwapQuoteResult, SwapResult, SwapRouteResult, T2000, T2000Error, T2000Options, TransactionRecord, TransactionSigner, type TrustMode, type VerifyAnchor, type VerifyCheck, type VerifyOptions, type VerifyResult, WRITE_APPENDER_REGISTRY, type WriteStep, type WriteToolName, ZkLoginProof, approxUsdValue, assertLimitConfig, buildAddLeafTx, buildRevokeLeafTx, chatCompletion, chatCompletionStream, clearLimits, composeTx, dailySpentToday, deriveAllowedAddressesFromPtb, displayHandle, exportPrivateKey, fullHandle, generateKeypair, getAddress, getLimits, getSponsoredSwapProviders, getSwapQuote, hasLimits, keypairFromPrivateKey, listModels, loadKey, looksLikeSuiNs, normalizeAddressInput, queryBalance, readLimitsFile, recordDailySpend, resolveAddressToSuinsViaRpc, resolveSuinsViaRpc, saveBech32, saveKey, setLimits, validateLabel, verifyReceipt, walletExists, writeLimitsFile };
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,9 @@ import { decodeSuiPrivateKey } from '@mysten/sui/cryptography';
|
|
|
11
11
|
import { access, mkdir, writeFile, readFile } from 'fs/promises';
|
|
12
12
|
import { join, dirname, resolve } from 'path';
|
|
13
13
|
import { homedir } from 'os';
|
|
14
|
+
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
15
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
16
|
+
import { hexToBytes, bytesToHex } from '@noble/hashes/utils';
|
|
14
17
|
import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
15
18
|
import { SuinsTransaction } from '@mysten/suins';
|
|
16
19
|
|
|
@@ -1220,10 +1223,10 @@ async function finalize(response, opts) {
|
|
|
1220
1223
|
return { status: response.status, body: body2, paid: opts.paid };
|
|
1221
1224
|
}
|
|
1222
1225
|
async function makeGrpcBuildClient(client) {
|
|
1223
|
-
const { SuiGrpcClient:
|
|
1226
|
+
const { SuiGrpcClient: SuiGrpcClient3 } = await import('@mysten/sui/grpc');
|
|
1224
1227
|
const network = client.network === "testnet" ? "testnet" : "mainnet";
|
|
1225
1228
|
const baseUrl = network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
|
|
1226
|
-
return new
|
|
1229
|
+
return new SuiGrpcClient3({ baseUrl, network });
|
|
1227
1230
|
}
|
|
1228
1231
|
function atomicToHuman(raw, decimals) {
|
|
1229
1232
|
return Number(raw) / 10 ** decimals;
|
|
@@ -2024,6 +2027,207 @@ async function listModels(opts) {
|
|
|
2024
2027
|
privacy: m.privacy ?? m.privacy_tier
|
|
2025
2028
|
}));
|
|
2026
2029
|
}
|
|
2030
|
+
var RECEIPT_ANCHORED_SUFFIX = "::anchor::ReceiptAnchored";
|
|
2031
|
+
function fullnodeUrl(network) {
|
|
2032
|
+
return network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
|
|
2033
|
+
}
|
|
2034
|
+
function jcs(value) {
|
|
2035
|
+
if (value === null) {
|
|
2036
|
+
return "null";
|
|
2037
|
+
}
|
|
2038
|
+
if (typeof value === "boolean") {
|
|
2039
|
+
return value ? "true" : "false";
|
|
2040
|
+
}
|
|
2041
|
+
if (typeof value === "number") {
|
|
2042
|
+
if (!Number.isInteger(value)) {
|
|
2043
|
+
throw new Error("JCS: non-integer number");
|
|
2044
|
+
}
|
|
2045
|
+
return String(value);
|
|
2046
|
+
}
|
|
2047
|
+
if (typeof value === "string") {
|
|
2048
|
+
return JSON.stringify(value);
|
|
2049
|
+
}
|
|
2050
|
+
if (Array.isArray(value)) {
|
|
2051
|
+
return `[${value.map(jcs).join(",")}]`;
|
|
2052
|
+
}
|
|
2053
|
+
const keys = Object.keys(value).sort();
|
|
2054
|
+
return `{${keys.map((k) => `${JSON.stringify(k)}:${jcs(value[k])}`).join(",")}}`;
|
|
2055
|
+
}
|
|
2056
|
+
function verifyReceiptSignature(receipt, signingKeyHex) {
|
|
2057
|
+
try {
|
|
2058
|
+
const sig = receipt.signature;
|
|
2059
|
+
if (sig?.algo !== "ecdsa-secp256k1" || !sig.value) {
|
|
2060
|
+
return false;
|
|
2061
|
+
}
|
|
2062
|
+
const canonical = {
|
|
2063
|
+
api_version: receipt.api_version ?? "",
|
|
2064
|
+
receipt_id: receipt.receipt_id ?? "",
|
|
2065
|
+
chat_id: receipt.chat_id ?? null,
|
|
2066
|
+
workload_id: receipt.workload_id ?? "",
|
|
2067
|
+
workload_keyset_digest: receipt.workload_keyset_digest ?? "",
|
|
2068
|
+
endpoint: receipt.endpoint ?? "",
|
|
2069
|
+
method: receipt.method ?? "",
|
|
2070
|
+
served_at: receipt.served_at ?? 0,
|
|
2071
|
+
event_log: receipt.event_log ?? [],
|
|
2072
|
+
signature: { algo: sig.algo, key_id: sig.key_id ?? "" }
|
|
2073
|
+
};
|
|
2074
|
+
const prehash = sha256(new TextEncoder().encode(jcs(canonical)));
|
|
2075
|
+
const sigBytes = hexToBytes(sig.value);
|
|
2076
|
+
if (sigBytes.length !== 65) {
|
|
2077
|
+
return false;
|
|
2078
|
+
}
|
|
2079
|
+
let v = sigBytes[64];
|
|
2080
|
+
if (v >= 27 && v <= 30) {
|
|
2081
|
+
v -= 27;
|
|
2082
|
+
}
|
|
2083
|
+
if (v > 3) {
|
|
2084
|
+
return false;
|
|
2085
|
+
}
|
|
2086
|
+
const recovered = secp256k1.Signature.fromCompact(sigBytes.slice(0, 64)).addRecoveryBit(v).recoverPublicKey(prehash).toHex(false);
|
|
2087
|
+
const endorsed = bytesToHex(hexToBytes(signingKeyHex.replace(/^0x/, "")));
|
|
2088
|
+
return recovered.toLowerCase() === endorsed.toLowerCase();
|
|
2089
|
+
} catch {
|
|
2090
|
+
return false;
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
async function verifyReceipt(receiptId, opts = {}) {
|
|
2094
|
+
const base = opts.apiBase ?? DEFAULT_API_BASE;
|
|
2095
|
+
const network = opts.network ?? "mainnet";
|
|
2096
|
+
const checks = [];
|
|
2097
|
+
let receipt = null;
|
|
2098
|
+
try {
|
|
2099
|
+
const res = await fetch(`${base}/aci/receipts/${encodeURIComponent(receiptId)}`);
|
|
2100
|
+
if (res.ok) {
|
|
2101
|
+
receipt = await res.json();
|
|
2102
|
+
}
|
|
2103
|
+
} catch {
|
|
2104
|
+
}
|
|
2105
|
+
if (!receipt?.event_log) {
|
|
2106
|
+
checks.push({
|
|
2107
|
+
name: "Receipt",
|
|
2108
|
+
status: "fail",
|
|
2109
|
+
detail: "receipt not found or malformed",
|
|
2110
|
+
trust: "receipt-asserted"
|
|
2111
|
+
});
|
|
2112
|
+
return { receiptId, verified: false, anchorVerified: false, checks };
|
|
2113
|
+
}
|
|
2114
|
+
const wireHash = receipt.event_log.find((e) => e.type === "response.returned")?.wire_hash;
|
|
2115
|
+
const workloadId = receipt.workload_id;
|
|
2116
|
+
checks.push({
|
|
2117
|
+
name: "Receipt",
|
|
2118
|
+
status: wireHash && workloadId ? "pass" : "fail",
|
|
2119
|
+
detail: wireHash ? `well-formed (${receipt.event_log.length} log entries, workload ${workloadId})` : "missing response wire_hash / workload_id",
|
|
2120
|
+
trust: "receipt-asserted"
|
|
2121
|
+
});
|
|
2122
|
+
const upstreamEv = receipt.event_log.find((e) => e.type === "upstream.verified");
|
|
2123
|
+
const upstreamOk = upstreamEv?.result === "verified";
|
|
2124
|
+
checks.push({
|
|
2125
|
+
name: "Confidential upstream",
|
|
2126
|
+
status: upstreamEv ? upstreamOk ? "pass" : "fail" : "skip",
|
|
2127
|
+
detail: upstreamEv ? `${upstreamEv.provider ?? upstreamEv.upstream_name ?? "upstream"}: ${upstreamEv.result ?? "unknown"}${upstreamEv.tcb_status ? ` (TCB ${upstreamEv.tcb_status})` : ""}` : "no upstream.verified event (routed/non-confidential?)",
|
|
2128
|
+
trust: "receipt-asserted"
|
|
2129
|
+
});
|
|
2130
|
+
let anchorVerified = false;
|
|
2131
|
+
let anchor;
|
|
2132
|
+
let digest;
|
|
2133
|
+
try {
|
|
2134
|
+
const res = await fetch(`${base}/aci/anchor/${encodeURIComponent(receiptId)}`);
|
|
2135
|
+
if (res.ok) {
|
|
2136
|
+
const j = await res.json();
|
|
2137
|
+
digest = j.txDigest;
|
|
2138
|
+
}
|
|
2139
|
+
} catch {
|
|
2140
|
+
}
|
|
2141
|
+
if (!digest) {
|
|
2142
|
+
checks.push({
|
|
2143
|
+
name: "Sui anchor",
|
|
2144
|
+
status: "fail",
|
|
2145
|
+
detail: `no anchor on record \u2014 POST ${base}/aci/anchor/${receiptId} to create one`,
|
|
2146
|
+
trust: "trustless"
|
|
2147
|
+
});
|
|
2148
|
+
} else {
|
|
2149
|
+
try {
|
|
2150
|
+
const client = new SuiGrpcClient({ baseUrl: fullnodeUrl(network), network });
|
|
2151
|
+
const tx = await client.core.getTransaction({
|
|
2152
|
+
digest,
|
|
2153
|
+
include: { events: true }
|
|
2154
|
+
});
|
|
2155
|
+
const txn = tx.$kind === "Transaction" ? tx.Transaction : tx.FailedTransaction;
|
|
2156
|
+
const ev = (txn.events ?? []).find(
|
|
2157
|
+
(e) => e.eventType.endsWith(RECEIPT_ANCHORED_SUFFIX)
|
|
2158
|
+
);
|
|
2159
|
+
const data = ev?.json ?? {};
|
|
2160
|
+
const onChainReceipt = String(data.receipt_id ?? "");
|
|
2161
|
+
const onChainWire = String(data.wire_hash ?? "");
|
|
2162
|
+
const onChainWorkload = String(data.workload_id ?? "");
|
|
2163
|
+
const matches = onChainReceipt === receiptId && onChainWire === wireHash && onChainWorkload === workloadId;
|
|
2164
|
+
anchorVerified = matches;
|
|
2165
|
+
anchor = {
|
|
2166
|
+
txDigest: digest,
|
|
2167
|
+
anchoredAtMs: data.anchored_at_ms ? String(data.anchored_at_ms) : void 0,
|
|
2168
|
+
anchoredBy: data.anchored_by ? String(data.anchored_by) : void 0,
|
|
2169
|
+
explorer: `https://suiscan.xyz/${network}/tx/${digest}`
|
|
2170
|
+
};
|
|
2171
|
+
checks.push({
|
|
2172
|
+
name: "Sui anchor",
|
|
2173
|
+
status: matches ? "pass" : "fail",
|
|
2174
|
+
detail: matches ? `on-chain ReceiptAnchored matches (wire_hash + workload_id), tx ${digest}` : `on-chain event does NOT match the receipt (wire ${onChainWire || "absent"})`,
|
|
2175
|
+
trust: "trustless"
|
|
2176
|
+
});
|
|
2177
|
+
} catch (e) {
|
|
2178
|
+
checks.push({
|
|
2179
|
+
name: "Sui anchor",
|
|
2180
|
+
status: "fail",
|
|
2181
|
+
detail: `could not read anchor tx ${digest}: ${e instanceof Error ? e.message : "error"}`,
|
|
2182
|
+
trust: "trustless"
|
|
2183
|
+
});
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
let signatureForged = false;
|
|
2187
|
+
let sigStatus = "skip";
|
|
2188
|
+
let sigDetail = "no signature on receipt";
|
|
2189
|
+
if (receipt.signature?.value) {
|
|
2190
|
+
try {
|
|
2191
|
+
const model = opts.model ?? "phala/glm-5.2";
|
|
2192
|
+
const res = await fetch(
|
|
2193
|
+
`${base}/aci/attestation?model=${encodeURIComponent(model)}`
|
|
2194
|
+
);
|
|
2195
|
+
const att = res.ok ? await res.json() : null;
|
|
2196
|
+
if (!att?.signingKey) {
|
|
2197
|
+
sigDetail = "could not fetch the attested keyset to check the signature";
|
|
2198
|
+
} else if (att.workloadId && att.workloadId !== workloadId) {
|
|
2199
|
+
sigDetail = `attested keyset is for a different workload \u2014 pass --model for ${workloadId}`;
|
|
2200
|
+
} else {
|
|
2201
|
+
const ok = verifyReceiptSignature(receipt, att.signingKey);
|
|
2202
|
+
sigStatus = ok ? "pass" : "fail";
|
|
2203
|
+
signatureForged = !ok;
|
|
2204
|
+
sigDetail = ok ? `signed by the attested receipt key (${receipt.signature.key_id ?? "key"})` : "signature does NOT recover the attested receipt key \u2014 forged/altered";
|
|
2205
|
+
}
|
|
2206
|
+
} catch {
|
|
2207
|
+
sigDetail = "signature check errored";
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
checks.push({
|
|
2211
|
+
name: "Receipt signature",
|
|
2212
|
+
status: sigStatus,
|
|
2213
|
+
detail: sigDetail,
|
|
2214
|
+
trust: sigStatus === "skip" ? "roadmap" : "trustless"
|
|
2215
|
+
});
|
|
2216
|
+
return {
|
|
2217
|
+
receiptId,
|
|
2218
|
+
verified: Boolean(wireHash && workloadId) && anchorVerified && !signatureForged,
|
|
2219
|
+
anchorVerified,
|
|
2220
|
+
checks,
|
|
2221
|
+
wireHash,
|
|
2222
|
+
workloadId,
|
|
2223
|
+
upstream: upstreamEv ? {
|
|
2224
|
+
provider: upstreamEv.provider ?? upstreamEv.upstream_name,
|
|
2225
|
+
result: upstreamEv.result,
|
|
2226
|
+
tcbStatus: upstreamEv.tcb_status
|
|
2227
|
+
} : void 0,
|
|
2228
|
+
anchor
|
|
2229
|
+
};
|
|
2230
|
+
}
|
|
2027
2231
|
var DEFAULT_CONFIG_DIR = join(homedir(), ".t2000");
|
|
2028
2232
|
function resolveConfigPath(configDir) {
|
|
2029
2233
|
return join(configDir ?? DEFAULT_CONFIG_DIR, "config.json");
|
|
@@ -2309,6 +2513,11 @@ var T2000 = class _T2000 extends EventEmitter {
|
|
|
2309
2513
|
async models(opts) {
|
|
2310
2514
|
return listModels(opts);
|
|
2311
2515
|
}
|
|
2516
|
+
/** Verify a confidential response by receipt id — checks the signed receipt
|
|
2517
|
+
* + its trustless on-chain Sui anchor. Fails closed on any mismatch. */
|
|
2518
|
+
async verify(receiptId, opts) {
|
|
2519
|
+
return verifyReceipt(receiptId, opts);
|
|
2520
|
+
}
|
|
2312
2521
|
// -- Swap --
|
|
2313
2522
|
async swap(params) {
|
|
2314
2523
|
this.limits.assert({
|
|
@@ -3067,6 +3276,6 @@ function displayHandle(label, parentName = AUDRIC_PARENT_NAME) {
|
|
|
3067
3276
|
// src/index.ts
|
|
3068
3277
|
init_preflight();
|
|
3069
3278
|
|
|
3070
|
-
export { AGENT_ID_PARENT, AGENT_ID_PARENT_NAME, AGENT_ID_PARENT_NFT_ID, AUDRIC_PARENT, AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, CETUS_USDC_SUI_POOL, CLOCK_ID, COIN_REGISTRY, DEFAULT_API_BASE, DEFAULT_GRPC_URL, DEFAULT_NETWORK, ETH_TYPE, GASLESS_MIN_STABLE_AMOUNT, GASLESS_STABLE_TYPES, GAS_RESERVE_MIN, IKA_TYPE, InvalidAddressError, KNOWN_TARGETS, KeypairSigner, LABEL_PATTERNS, LOFI_TYPE, LimitEnforcer, LimitExceededError, MANIFEST_TYPE, MIST_PER_SUI, NAVX_TYPE, OPERATION_ASSETS, OVERLAY_FEE_RATE, PREFLIGHT_MAX_AMOUNT, PREFLIGHT_OK, SENDABLE_ASSETS, SPONSORED_PYTH_DEPENDENT_PROVIDERS, STABLE_ASSETS, SUINS_NAME_REGEX, SUI_ADDRESS_REGEX, SUI_ADDRESS_STRICT_REGEX, SUI_DECIMALS, SUI_TYPE, SUPPORTED_ASSETS, SuinsNotRegisteredError, SuinsRpcError, T2000, T2000Error, T2000_OVERLAY_FEE_WALLET, TOKEN_MAP, USDC_DECIMALS, USDC_TYPE, USDE_TYPE, USDSUI_TYPE, USDT_TYPE, WAL_TYPE, WBTC_TYPE, WRITE_APPENDER_REGISTRY, ZkLoginSigner, addSendToTx, addSwapToTx, approxUsdValue, assertAllowedAsset, assertLimitConfig, buildAddLeafTx, buildRevokeLeafTx, buildSendTx, buildSwapTx, chatCompletion, chatCompletionStream, checkPositiveAmount, checkSuiAddress, classifyAction, classifyLabel, classifyTransaction, clearLimits, composeTx, dailySpentToday, deriveAllowedAddressesFromPtb, deserializeCetusRoute, displayHandle, executeTx, exportPrivateKey, extractAllUserLegs, extractTransferDetails, extractTxCommands, extractTxSender, fallbackLabel, fetchAllCoins, findSwapRoute, formatAssetAmount, formatSui, formatUsd, fullHandle, generateKeypair, getAddress, getCoinMeta, getDecimals, getDecimalsForCoinType, getLimits, getSponsoredSwapProviders, getSuiClient, getSuiGrpcClient, getSwapQuote, hasLimits, isAllowedAsset, isCetusRouteFresh, isInRegistry, keypairFromPrivateKey, listModels, loadKey, looksLikeSuiNs, mapMoveAbortCode, mapWalletError, mistToSui, normalizeAddressInput, normalizeAsset, normalizeCoinType, parseSuiRpcTx, payWithMpp, preflightFail, preflightPay, preflightSend, preflightSwap, queryBalance, queryHistory, queryTransaction, rawToStable, rawToUsdc, readLimitsFile, recordDailySpend, refineLendingLabel, resolveAddressToSuinsViaRpc, resolveSuinsViaRpc, resolveSymbol, resolveTokenType, saveBech32, saveKey, selectAndSplitCoin, selectSuiCoin, serializeCetusRoute, setLimits, simulateTransaction, stableToRaw, suiToMist, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, validateLabel, verifyCetusRouteCoinMatch, walletExists, writeLimitsFile };
|
|
3279
|
+
export { AGENT_ID_PARENT, AGENT_ID_PARENT_NAME, AGENT_ID_PARENT_NFT_ID, AUDRIC_PARENT, AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, CETUS_USDC_SUI_POOL, CLOCK_ID, COIN_REGISTRY, DEFAULT_API_BASE, DEFAULT_GRPC_URL, DEFAULT_NETWORK, ETH_TYPE, GASLESS_MIN_STABLE_AMOUNT, GASLESS_STABLE_TYPES, GAS_RESERVE_MIN, IKA_TYPE, InvalidAddressError, KNOWN_TARGETS, KeypairSigner, LABEL_PATTERNS, LOFI_TYPE, LimitEnforcer, LimitExceededError, MANIFEST_TYPE, MIST_PER_SUI, NAVX_TYPE, OPERATION_ASSETS, OVERLAY_FEE_RATE, PREFLIGHT_MAX_AMOUNT, PREFLIGHT_OK, SENDABLE_ASSETS, SPONSORED_PYTH_DEPENDENT_PROVIDERS, STABLE_ASSETS, SUINS_NAME_REGEX, SUI_ADDRESS_REGEX, SUI_ADDRESS_STRICT_REGEX, SUI_DECIMALS, SUI_TYPE, SUPPORTED_ASSETS, SuinsNotRegisteredError, SuinsRpcError, T2000, T2000Error, T2000_OVERLAY_FEE_WALLET, TOKEN_MAP, USDC_DECIMALS, USDC_TYPE, USDE_TYPE, USDSUI_TYPE, USDT_TYPE, WAL_TYPE, WBTC_TYPE, WRITE_APPENDER_REGISTRY, ZkLoginSigner, addSendToTx, addSwapToTx, approxUsdValue, assertAllowedAsset, assertLimitConfig, buildAddLeafTx, buildRevokeLeafTx, buildSendTx, buildSwapTx, chatCompletion, chatCompletionStream, checkPositiveAmount, checkSuiAddress, classifyAction, classifyLabel, classifyTransaction, clearLimits, composeTx, dailySpentToday, deriveAllowedAddressesFromPtb, deserializeCetusRoute, displayHandle, executeTx, exportPrivateKey, extractAllUserLegs, extractTransferDetails, extractTxCommands, extractTxSender, fallbackLabel, fetchAllCoins, findSwapRoute, formatAssetAmount, formatSui, formatUsd, fullHandle, generateKeypair, getAddress, getCoinMeta, getDecimals, getDecimalsForCoinType, getLimits, getSponsoredSwapProviders, getSuiClient, getSuiGrpcClient, getSwapQuote, hasLimits, isAllowedAsset, isCetusRouteFresh, isInRegistry, keypairFromPrivateKey, listModels, loadKey, looksLikeSuiNs, mapMoveAbortCode, mapWalletError, mistToSui, normalizeAddressInput, normalizeAsset, normalizeCoinType, parseSuiRpcTx, payWithMpp, preflightFail, preflightPay, preflightSend, preflightSwap, queryBalance, queryHistory, queryTransaction, rawToStable, rawToUsdc, readLimitsFile, recordDailySpend, refineLendingLabel, resolveAddressToSuinsViaRpc, resolveSuinsViaRpc, resolveSymbol, resolveTokenType, saveBech32, saveKey, selectAndSplitCoin, selectSuiCoin, serializeCetusRoute, setLimits, simulateTransaction, stableToRaw, suiToMist, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, validateLabel, verifyCetusRouteCoinMatch, verifyReceipt, walletExists, writeLimitsFile };
|
|
3071
3280
|
//# sourceMappingURL=index.js.map
|
|
3072
3281
|
//# sourceMappingURL=index.js.map
|