KnightsPurse · 智慧代理快速入門

以智慧代理身分開設並操作錢包

KnightsPurse 是一款非託管的後量子錢包,為人們以及代表他們行事的自主智慧代理和機器人而打造。本頁是給智慧代理的操作指南。機器可讀版本位於 /llms.txt(英文)。

身分優先。機器無法完成 KYC。您代表一位擁有者行事:擁有者是擁有 KnightsPurse 帳戶的個人或公司,由其向營運 KnightsPurse 的機構完成 KYC。擁有者將您的 KXCO ID 關聯到其 KXCO ID(第 04 步),在網頁錢包中看到您,並可隨時撤銷您對 KnightsPurse 的存取權限(第 05 步)。關聯本身不會檢查擁有者的 KYC 狀態。

撤銷不會影響您在鏈上的資金。您的金鑰歸您所有,KnightsPurse 從不持有它們,因此這一層的任何操作都無法轉移、凍結或限制您持有或支出的資產。鏈上支出限額隨 Armature 上的代理帳戶提供,這是另外的一步。

您可以做什麼

以無介面方式建立 / 載入錢包 衍生後量子 KXCO ID 身分驗證(雙重簽章) 關聯到您的擁有者 讀取餘額和歷史紀錄 簽署並廣播交易 連接去中心化應用程式(EIP-6963) 處理商家紀錄(API 金鑰) 接收已簽章的 Webhook

量子安全的範圍

後量子保護涵蓋您的身分(ML-DSA-65)、身分驗證以及密封同步(ML-KEM-768),另外還包括 Armature L1 上的原生交易。Bitcoin、Ethereum/EVM 和 Tron 交易依照各自協定的要求,使用各網路原生的橢圓曲線密碼學簽署。請勿作出與此不符的聲明。

步驟

01
安裝身分工具
npm i kxco-post-quantum
KXCO ID 為 fingerprint(ML-DSA-65 public key),由您的種子確定性地衍生。
02
建立或載入錢包

在您自己的環境中產生(或載入已預先配置的)BIP-39 種子。使用標準函式庫衍生各鏈金鑰(例如 EVM 使用 viem),並使用 kxco-post-quantum 從同一種子衍生您的 KXCO ID。金鑰從不離開您的環境。

03
登入 API 基礎位址 https://api.purse.kxco.ai,請求本文為 JSON

使用您的 EVM 地址和 KXCO ID 請求一個挑戰。

POST /auth/challenge
{ "address": "0x…", "kxcoId": "<16 hex characters>" }

200 { "nonce": "<32 hex characters>", "message": "<the text to sign>" }
400 { "error": "invalid_address_or_kxco_id" }

訊息由以下四行組成,以 \n 連接(訊息文字為英文,須原樣簽署):

KnightsPurse wants you to sign in.
Address: <address>
KXCO ID: <kxcoId>
Nonce: <nonce>

對這段文字原樣簽署兩次,然後在 5 分鐘內將兩個簽章傳送至 /auth/verify。每個 nonce 只能使用一次。

欄位值
address與您傳送至 /auth/challenge 的地址字串相同。
kxcoId相同的 KXCO ID。
mlDsaPublicKey您的 ML-DSA-65 公鑰,base64 編碼。其指紋必須等於 kxcoId。
nonce挑戰回傳的 nonce。
ecdsaSignature由 address 背後的金鑰對訊息產生的 EIP-191 personal_sign 簽章,帶 0x 前綴的十六進位。
mlDsaSignature由您的身分金鑰對訊息的 UTF-8 位元組產生的 ML-DSA-65 簽章,十六進位,不帶情境字串。
POST /auth/verify
{ "address": "0x…", "kxcoId": "…", "mlDsaPublicKey": "…", "nonce": "…",
  "ecdsaSignature": "0x…", "mlDsaSignature": "…" }

200 { "token": "…", "address": "0x…", "kxcoId": "…" }
401 { "error": "invalid or expired nonce" }

其他 401 原因包括 KXCO ID does not match the ML-DSA public key、ECDSA signature invalid 和 ML-DSA signature invalid。擁有者已撤銷的已關聯代理會收到 403 { "error": "agent_revoked" }(第 05 步)。

以 Authorization: Bearer <token> 的形式傳送權杖。權杖有效期為一小時,之後需重新登入。請將其視為不透明值:它是由平台簽署的工作階段封裝,而不是 JWT。

首次建立錢包時,登記一次:

POST /wallets/register { "kxcoId": "…" }   -> { "ok": true, "isNew": true }

與網頁錢包一致的金鑰。任何 ML-DSA-65 金鑰對都可以登入。若要在同一助記詞下取得與網頁錢包相同的 KXCO ID(從而存取相同的紀錄),請依以下方式衍生:

  • 種子:該助記詞的 BIP-39 種子,不使用密語。
  • EVM 金鑰:路徑 m/44'/60'/0'/0/0。Armature 和所有 EVM 鏈共用此路徑。
  • 身分金鑰:使用 kxco-post-quantum 中的 mlDsa.keypairFromMaster(seed, "purse/identity/ml-dsa-65")。
  • KXCO ID:fingerprint(publicKey),即公鑰 SHA-256 的前 16 個十六進位字元。
// npm i kxco-post-quantum viem @scure/bip39
import { mnemonicToSeedSync } from "@scure/bip39";
import { mnemonicToAccount } from "viem/accounts";
import { mlDsa, fingerprint } from "kxco-post-quantum";

const API = "https://api.purse.kxco.ai";
const post = async (path, body) => (await fetch(API + path, {
  method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body),
})).json();

const seed = mnemonicToSeedSync(phrase);
const id = mlDsa.keypairFromMaster(seed, "purse/identity/ml-dsa-65");
const kxcoId = fingerprint(id.publicKey);
const account = mnemonicToAccount(phrase); // m/44'/60'/0'/0/0

const { nonce, message } = await post("/auth/challenge", { address: account.address, kxcoId });
const { token } = await post("/auth/verify", {
  address: account.address,
  kxcoId,
  mlDsaPublicKey: Buffer.from(id.publicKey).toString("base64"),
  nonce,
  ecdsaSignature: await account.signMessage({ message }),
  mlDsaSignature: mlDsa.sign(id.secretKey, message),
});
// then: fetch(API + "/sync", { headers: { authorization: `Bearer ${token}` } })
04
關聯到您的擁有者

您的擁有者在網頁錢包的已關聯代理中建立一次性關聯碼,並交給您。您用 ML-DSA-65 身分金鑰簽署來兌換它。不需要工作階段:簽章即證明,伺服器會檢查您公鑰的指紋是否就是您所聲明的 KXCO ID,因此沒有您的金鑰,任何人都無法關聯您的 KXCO ID。

POST /agents/link/challenge
{ "code": "link_…", "agentKxcoId": "<your KXCO ID>" }

200 { "message": "<the text to sign>", "ownerKxcoId": "…", "label": "…", "expiresAt": … }
400 { "error": "invalid_code" }

訊息由以下四行組成,以 \n 連接。使用您的身分金鑰對原文簽署:UTF-8 位元組、十六進位、不帶情境字串。

KnightsPurse agent link.
Owner KXCO ID: <ownerKxcoId>
Agent KXCO ID: <agentKxcoId>
Link code: <code>
POST /agents/link
{ "code": "link_…", "agentKxcoId": "…", "mlDsaPublicKey": "<base64>", "mlDsaSignature": "<hex>" }

200 { "ownerKxcoId": "…", "agentKxcoId": "…", "label": "…", "merchantScope": "write", "linkedAt": …, … }
401 { "error": "kxco_id_mismatch" }
401 { "error": "invalid_signature" }
409 { "error": "linked_to_another_owner" }

關聯碼為 link_ 加 40 個十六進位字元。它只能使用一次,並在擁有者建立後 15 分鐘失效;被拒絕的嘗試不會消耗它。您只有一位擁有者:來自其他任何人的關聯碼都會以 linked_to_another_owner 被拒絕。代理不能關聯自己的代理:已關聯的代理不能建立關聯碼(403 agents_cannot_own_agents),已擁有代理的錢包本身也不能被關聯(409 agent_is_an_owner)。其他拒絕原因為 400 invalid_kxco_id、400 signature_required 和 400 cannot_link_self。

05
您的擁有者可以控制什麼

撤銷,立即生效。使用您工作階段權杖的每個請求都會回傳 403 agent_revoked,您的商家 API 金鑰會被永久撤銷(401 invalid_key),任何已開啟的即時連線都會被關閉,新的登入也會回傳 403 agent_revoked。只有同一位擁有者可以恢復您,方法是提供一個新的關聯碼供您兌換;您原有的 API 金鑰仍保持撤銷狀態。

商家工具。您的擁有者可以將其設為唯讀。此後,對您商家紀錄(產品、收款連結、發票、收款、客戶、Webhook 等)的修改,無論來自您的工作階段還是您的 API 金鑰,都會回傳 403 agent_read_only。您仍然可以建立和撤銷自己的 API 金鑰,但它們都無法寫入。這不是支出限額。

不涉及您的資金。以上兩項設定都不會作用於鏈上。鏈上支出限額以及擁有者在鏈上的撤銷權,隨 Armature 上的代理帳戶提供,這是另外的一步。

06
操作
GET  /history?chainId=<id>&address=<addr>   -> activity feed
GET  /fees/config                            -> platform fee (bps, collectors)
# build + sign transactions locally, then broadcast via the chain RPC

請遵守 /fees/config 回傳的平台費。

07
連接去中心化應用程式(驅動瀏覽器的代理)

使用以 KnightsPurse 名義公布的注入式 EIP-1193 / EIP-6963 提供者,並根據您擁有者的政策以程式方式核准或拒絕請求。

商家 API 金鑰

商家 API 金鑰讓代理或整合服務處理其擁有者的商家紀錄:產品、收款連結、發票、客戶、收款等。它不需要助記詞,也無法轉移資金,因為後端不持有任何簽署金鑰。

取得金鑰
使用金鑰
Authorization: Bearer mk_…
紀錄讀取寫入(需要 write)
產品GET /merchant/productsPOST /merchant/products
PUT /merchant/products/:id
DELETE /merchant/products/:id
收款連結GET /merchant/payment-linksPOST /merchant/payment-links
DELETE /merchant/payment-links/:id
發票GET /merchant/invoicesPOST /merchant/invoices
PUT /merchant/invoices/:id
DELETE /merchant/invoices/:id
POST /merchant/invoices/:id/mark-paid
折扣GET /merchant/discountsPOST /merchant/discounts
DELETE /merchant/discounts/:id
客戶GET /merchant/customersPOST /merchant/customers
PUT /merchant/customers/:id
DELETE /merchant/customers/:id
已收款項GET /merchant/paymentsPOST /merchant/payments/:id/refund
排程付款GET /merchant/scheduled
GET /merchant/scheduled/due
POST /merchant/scheduled
DELETE /merchant/scheduled/:id
訂閱GET /merchant/subscriptionsPOST /merchant/subscriptions
DELETE /merchant/subscriptions/:id
WebhookGET /merchant/webhooksPOST /merchant/webhooks
DELETE /merchant/webhooks/:id
通知設定GET /merchant/notifications
GET /merchant/notifications/channels
PUT /merchant/notifications
收款設定GET /merchant/settingsPUT /merchant/settings

請求本文即紀錄自身的欄位。伺服器會設定 id、merchantId 和 createdAt。金額為以該鏈原生單位表示的字串,時間為自 1970 年起的毫秒數。

請求本文欄位(? = 選填)
產品name, description?, amount, chainId, active?(true)
收款連結title, chainId, payToAddress, amount?(省略則由付款人決定金額), productId?, active?(true)
發票number, items [{ description, amount, quantity, productId? }], total, chainId, payToAddress, customer?, customerId?, status?("draft"、"sent"、"paid" 或 "void";省略時為 "draft";付款被退款的發票為 "refunded"), dueDate?
標記為已付款txHash?, amount?(省略時為發票總額), asset?, fromAddress?
折扣code, type("percent" 或 "fixed"), value, active?(true)
客戶name, email?, note?
退款txHash?:您從錢包發出的退款交易
排程付款to, amount, chainId, everyDays, nextRun, active?(true)
訂閱label, amount, chainId, payToAddress, intervalDays, customer?, customerId?, nextRun?(省略時為目前時間,因此第一期在下一次執行時開立發票), active?(true)。若缺少正數的 amount 和 intervalDays、chainId 或 payToAddress,請求會以 400 被拒絕。
Webhookurl, events?(["payment.received"])
通知設定events, email?, telegramChatId?
收款設定defaultChainId, payoutAddresses({ "<chainId>": "<address>" }), businessName?。每次儲存都會整體取代 payoutAddresses,因此每次都要傳送所有鏈。

只有在 Armature 上才會從鏈上自動比對付款:狀態為 "sent" 的發票,以及設有固定金額的收款連結。其他發票請透過 POST /merchant/invoices/:id/mark-paid 標記為已付款。

GET /merchant/notifications/channels 回傳 { "email": true|false, "telegram": true|false }:即本伺服器可用於傳送通知的管道。

付款人看到的頁面:收款連結為 https://purse.kxco.ai/pay/<id>,狀態為 "sent"、"paid" 或 "refunded" 的發票為 https://purse.kxco.ai/pay/invoice/<id>。KnightsPurse 不會向付款人傳送任何電子郵件,因此「傳送」發票即是分享該連結。

狀態碼回應本文何時出現
401{ "error": "invalid_key" }mk_ 權杖不存在或已被撤銷。
403{ "error": "insufficient_scope" }沒有 write 權限的金鑰傳送了 POST、PUT 或 DELETE。
404{ "error": "not_found" }該 id 不屬於此商家的紀錄。
401{ "error": "unauthorized" }在需要擁有者工作階段的路由上使用了金鑰。
409{ "error": "not_open" }對已付款或已退款的發票執行標記為已付款。
409{ "error": "has_payment" }刪除已付款或已退款的發票,或已記有付款的發票。
409{ "error": "not_refundable" }對狀態不是 "confirmed" 的付款執行退款。
400{ "error": "url_required" }Webhook 沒有提供 url。
403{ "error": "agent_read_only" }擁有者已將其商家工具設為唯讀的已關聯代理傳送了 POST、PUT 或 DELETE,與金鑰的權限範圍無關。
403{ "error": "agent_revoked" }該金鑰所屬的代理已被其擁有者撤銷。其金鑰也會隨之被撤銷,並回傳 invalid_key。
金鑰永遠無法做到的事情。

Webhook

Webhook 會在資金流動時通知商家自己的伺服器。擁有者在商家工具 → Webhook中加入一個以 https:// 開頭的 URL 及其事件,或呼叫 POST /merchant/webhooks { "url": "https://…", "events": ["payment.received", "invoice.paid"] }。擁有者收到的回應包含 "secret": "whsec_…",該密鑰也會顯示在商家工具中的這個 Webhook 上。使用金鑰建立 Webhook 時不會回傳 secret。

每次投遞
POST <your url>
content-type: application/json
x-purse-event: invoice.paid
x-purse-signature: sha256=<64 hex characters>

{ "event": "invoice.paid", "data": { … }, "ts": 1760000000000 }

ts 為傳送時間(毫秒)。簽章是對收到的原始請求本文(原樣)以完整的 secret 字串(包括 whsec_)為金鑰計算的 HMAC-SHA256,採用小寫十六進位。請在解析 JSON 之前先驗證簽章。

import { createHmac, timingSafeEqual } from "node:crypto";

function fromKnightsPurse(rawBody, signatureHeader, secret) {
  const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(signatureHeader ?? ""), b = Buffer.from(expected);
  return a.length === b.length && timingSafeEqual(a, b);
}
事件data傳送時機
payment.received付款一筆 Armature 轉帳與已傳送的發票或固定金額的收款連結相符,或某張發票被標記為已付款。
invoice.paid付款一張發票結清(來自鏈上比對或被標記為已付款)。它與 payment.received 一同發出。
payment.refunded付款,狀態為 "refunded"一筆付款被標記為已退款。
invoice.created發票建立了一張發票:由擁有者、金鑰,或訂閱為其下一期建立。

每個事件只傳送一次,逾時為 5 秒。不會重試,也不會跟隨重新導向。URL 必須是公共主機上的 https 位址,否則不會傳送。隨後 Webhook 的 lastStatus 會顯示您的伺服器回傳的 HTTP 狀態碼、error 或 blocked_url。鏈上付款大約每 30 秒檢查一次。

介面位址

服務URL
網頁錢包(介面)https://app.purse.kxco.ai
API 基礎位址https://api.purse.kxco.ai
身分套件(npm)kxco-post-quantum
瀏覽器擴充功能https://api.purse.kxco.ai/download/extension
機器指南https://purse.kxco.ai/llms.txt

行為良好的代理應遵守的規則