kontext-sdk 0.10.0 → 0.11.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/README.md +57 -265
- package/dist/index.d.mts +309 -2
- package/dist/index.d.ts +309 -2
- package/dist/index.js +721 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +719 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -3625,7 +3625,9 @@ var FEATURE_MIN_PLAN = {
|
|
|
3625
3625
|
"unified-screening": "pro",
|
|
3626
3626
|
"blocklist-manager": "pro",
|
|
3627
3627
|
"kya-identity": "pro",
|
|
3628
|
-
"kya-behavioral": "enterprise"
|
|
3628
|
+
"kya-behavioral": "enterprise",
|
|
3629
|
+
"coinbase-wallets": "enterprise",
|
|
3630
|
+
"metamask-wallets": "enterprise"
|
|
3629
3631
|
};
|
|
3630
3632
|
var PLAN_RANK = { free: 0, pro: 1, enterprise: 2 };
|
|
3631
3633
|
var FEATURE_LABELS = {
|
|
@@ -3644,7 +3646,9 @@ var FEATURE_LABELS = {
|
|
|
3644
3646
|
"unified-screening": "Unified screening (OFAC, Chainalysis, OpenSanctions)",
|
|
3645
3647
|
"blocklist-manager": "Custom blocklist/allowlist manager",
|
|
3646
3648
|
"kya-identity": "KYA identity resolution (declared identity, wallet clustering)",
|
|
3647
|
-
"kya-behavioral": "KYA behavioral fingerprinting (cross-session linking, confidence scoring)"
|
|
3649
|
+
"kya-behavioral": "KYA behavioral fingerprinting (cross-session linking, confidence scoring)",
|
|
3650
|
+
"coinbase-wallets": "Coinbase Developer Platform Wallets",
|
|
3651
|
+
"metamask-wallets": "MetaMask Embedded Wallets"
|
|
3648
3652
|
};
|
|
3649
3653
|
function isFeatureAvailable(feature, currentPlan) {
|
|
3650
3654
|
const requiredPlan = FEATURE_MIN_PLAN[feature];
|
|
@@ -5610,6 +5614,602 @@ var KYAConfidenceScorer = class {
|
|
|
5610
5614
|
}
|
|
5611
5615
|
};
|
|
5612
5616
|
|
|
5617
|
+
// src/integrations/circle-wallets.ts
|
|
5618
|
+
var DEFAULT_BASE_URL = "https://api.circle.com";
|
|
5619
|
+
var REQUEST_TIMEOUT_MS = 1e4;
|
|
5620
|
+
var CircleWalletManager = class {
|
|
5621
|
+
apiKey;
|
|
5622
|
+
entitySecret;
|
|
5623
|
+
baseUrl;
|
|
5624
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5625
|
+
kontext = null;
|
|
5626
|
+
constructor(config) {
|
|
5627
|
+
if (!config.apiKey) {
|
|
5628
|
+
throw new KontextError(
|
|
5629
|
+
"INITIALIZATION_ERROR" /* INITIALIZATION_ERROR */,
|
|
5630
|
+
"Circle API key is required"
|
|
5631
|
+
);
|
|
5632
|
+
}
|
|
5633
|
+
if (!config.entitySecret) {
|
|
5634
|
+
throw new KontextError(
|
|
5635
|
+
"INITIALIZATION_ERROR" /* INITIALIZATION_ERROR */,
|
|
5636
|
+
"Circle entity secret is required"
|
|
5637
|
+
);
|
|
5638
|
+
}
|
|
5639
|
+
this.apiKey = config.apiKey;
|
|
5640
|
+
this.entitySecret = config.entitySecret;
|
|
5641
|
+
this.baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
|
|
5642
|
+
}
|
|
5643
|
+
/** Link to Kontext instance for auto-compliance logging */
|
|
5644
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5645
|
+
setKontext(kontext) {
|
|
5646
|
+
this.kontext = kontext;
|
|
5647
|
+
}
|
|
5648
|
+
/** Validate credentials by calling Circle's configuration endpoint */
|
|
5649
|
+
async validateCredentials() {
|
|
5650
|
+
try {
|
|
5651
|
+
const res = await fetch(`${this.baseUrl}/v1/w3s/config/entity`, {
|
|
5652
|
+
method: "GET",
|
|
5653
|
+
headers: this.headers(),
|
|
5654
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
5655
|
+
});
|
|
5656
|
+
return res.ok;
|
|
5657
|
+
} catch {
|
|
5658
|
+
return false;
|
|
5659
|
+
}
|
|
5660
|
+
}
|
|
5661
|
+
/** Create a wallet set (container for wallets) */
|
|
5662
|
+
async createWalletSet(input) {
|
|
5663
|
+
const body = {
|
|
5664
|
+
name: input.name,
|
|
5665
|
+
idempotencyKey: input.idempotencyKey ?? generateId(),
|
|
5666
|
+
entitySecretCiphertext: this.entitySecret
|
|
5667
|
+
};
|
|
5668
|
+
const res = await this.request(
|
|
5669
|
+
"POST",
|
|
5670
|
+
"/v1/w3s/developer/walletSets",
|
|
5671
|
+
body
|
|
5672
|
+
);
|
|
5673
|
+
return res.data.walletSet;
|
|
5674
|
+
}
|
|
5675
|
+
/** Create wallet(s) in a wallet set */
|
|
5676
|
+
async createWallet(input) {
|
|
5677
|
+
const body = {
|
|
5678
|
+
walletSetId: input.walletSetId,
|
|
5679
|
+
blockchains: input.blockchains.map((c) => this.mapChain(c)),
|
|
5680
|
+
count: input.count ?? 1,
|
|
5681
|
+
accountType: input.accountType ?? "EOA",
|
|
5682
|
+
idempotencyKey: input.idempotencyKey ?? generateId(),
|
|
5683
|
+
entitySecretCiphertext: this.entitySecret
|
|
5684
|
+
};
|
|
5685
|
+
const res = await this.request(
|
|
5686
|
+
"POST",
|
|
5687
|
+
"/v1/w3s/developer/wallets",
|
|
5688
|
+
body
|
|
5689
|
+
);
|
|
5690
|
+
return res.data.wallets;
|
|
5691
|
+
}
|
|
5692
|
+
/** List wallets, optionally filtered by wallet set */
|
|
5693
|
+
async listWallets(walletSetId) {
|
|
5694
|
+
const qs = walletSetId ? `?walletSetId=${walletSetId}` : "";
|
|
5695
|
+
const res = await this.request(
|
|
5696
|
+
"GET",
|
|
5697
|
+
`/v1/w3s/wallets${qs}`
|
|
5698
|
+
);
|
|
5699
|
+
return res.data.wallets;
|
|
5700
|
+
}
|
|
5701
|
+
/** Get wallet token balances */
|
|
5702
|
+
async getBalance(walletId) {
|
|
5703
|
+
const res = await this.request(
|
|
5704
|
+
"GET",
|
|
5705
|
+
`/v1/w3s/wallets/${walletId}/balances`
|
|
5706
|
+
);
|
|
5707
|
+
return res.data.tokenBalances.map((b) => ({
|
|
5708
|
+
token: b.token.symbol,
|
|
5709
|
+
amount: b.amount
|
|
5710
|
+
}));
|
|
5711
|
+
}
|
|
5712
|
+
/** Transfer with auto-compliance: runs verify() before/after transfer */
|
|
5713
|
+
async transferWithCompliance(input) {
|
|
5714
|
+
let complianceResult;
|
|
5715
|
+
if (this.kontext) {
|
|
5716
|
+
complianceResult = await this.kontext.verify({
|
|
5717
|
+
txHash: `circle-pending-${generateId()}`,
|
|
5718
|
+
chain: input.blockchain,
|
|
5719
|
+
amount: input.amount,
|
|
5720
|
+
token: "USDC",
|
|
5721
|
+
from: input.walletId,
|
|
5722
|
+
to: input.destinationAddress,
|
|
5723
|
+
agentId: input.agentId ?? "circle-wallet-manager"
|
|
5724
|
+
});
|
|
5725
|
+
if (!complianceResult.compliant) {
|
|
5726
|
+
return {
|
|
5727
|
+
id: "",
|
|
5728
|
+
state: "BLOCKED",
|
|
5729
|
+
complianceResult
|
|
5730
|
+
};
|
|
5731
|
+
}
|
|
5732
|
+
}
|
|
5733
|
+
const body = {
|
|
5734
|
+
walletId: input.walletId,
|
|
5735
|
+
tokenAddress: input.tokenAddress,
|
|
5736
|
+
destinationAddress: input.destinationAddress,
|
|
5737
|
+
amounts: [input.amount],
|
|
5738
|
+
blockchain: this.mapChain(input.blockchain),
|
|
5739
|
+
idempotencyKey: input.idempotencyKey ?? generateId(),
|
|
5740
|
+
entitySecretCiphertext: this.entitySecret,
|
|
5741
|
+
feeLevel: "MEDIUM"
|
|
5742
|
+
};
|
|
5743
|
+
const res = await this.request(
|
|
5744
|
+
"POST",
|
|
5745
|
+
"/v1/w3s/developer/transactions/transfer",
|
|
5746
|
+
body
|
|
5747
|
+
);
|
|
5748
|
+
if (this.kontext) {
|
|
5749
|
+
await this.kontext.logReasoning({
|
|
5750
|
+
agentId: input.agentId ?? "circle-wallet-manager",
|
|
5751
|
+
action: "circle-transfer",
|
|
5752
|
+
reasoning: `Circle transfer ${res.data.id}: ${input.amount} to ${input.destinationAddress} on ${input.blockchain}`,
|
|
5753
|
+
confidence: 1,
|
|
5754
|
+
context: { transferId: res.data.id, state: res.data.state }
|
|
5755
|
+
});
|
|
5756
|
+
}
|
|
5757
|
+
return {
|
|
5758
|
+
id: res.data.id,
|
|
5759
|
+
state: res.data.state,
|
|
5760
|
+
txHash: res.data.txHash,
|
|
5761
|
+
complianceResult
|
|
5762
|
+
};
|
|
5763
|
+
}
|
|
5764
|
+
// --------------------------------------------------------------------------
|
|
5765
|
+
// Private helpers
|
|
5766
|
+
// --------------------------------------------------------------------------
|
|
5767
|
+
headers() {
|
|
5768
|
+
return {
|
|
5769
|
+
"Authorization": `Bearer ${this.apiKey}`,
|
|
5770
|
+
"Content-Type": "application/json",
|
|
5771
|
+
"X-Entity-Secret": this.entitySecret
|
|
5772
|
+
};
|
|
5773
|
+
}
|
|
5774
|
+
async request(method, path6, body) {
|
|
5775
|
+
const res = await fetch(`${this.baseUrl}${path6}`, {
|
|
5776
|
+
method,
|
|
5777
|
+
headers: this.headers(),
|
|
5778
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
5779
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
5780
|
+
});
|
|
5781
|
+
if (!res.ok) {
|
|
5782
|
+
const text = await res.text().catch(() => "");
|
|
5783
|
+
throw new KontextError(
|
|
5784
|
+
"API_ERROR" /* API_ERROR */,
|
|
5785
|
+
`Circle API error ${res.status}: ${text}`
|
|
5786
|
+
);
|
|
5787
|
+
}
|
|
5788
|
+
return res.json();
|
|
5789
|
+
}
|
|
5790
|
+
mapChain(chain) {
|
|
5791
|
+
const map = {
|
|
5792
|
+
ethereum: "ETH",
|
|
5793
|
+
base: "BASE",
|
|
5794
|
+
polygon: "MATIC",
|
|
5795
|
+
arbitrum: "ARB",
|
|
5796
|
+
optimism: "OP",
|
|
5797
|
+
avalanche: "AVAX",
|
|
5798
|
+
solana: "SOL"
|
|
5799
|
+
};
|
|
5800
|
+
return map[chain] ?? chain.toUpperCase();
|
|
5801
|
+
}
|
|
5802
|
+
};
|
|
5803
|
+
|
|
5804
|
+
// src/integrations/coinbase-wallets.ts
|
|
5805
|
+
var CDP_BASE_URL = "https://api.cdp.coinbase.com";
|
|
5806
|
+
var REQUEST_TIMEOUT_MS2 = 1e4;
|
|
5807
|
+
var CoinbaseWalletManager = class {
|
|
5808
|
+
apiKeyId;
|
|
5809
|
+
apiKeySecret;
|
|
5810
|
+
walletSecret;
|
|
5811
|
+
baseUrl;
|
|
5812
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5813
|
+
kontext = null;
|
|
5814
|
+
constructor(config) {
|
|
5815
|
+
if (!config.apiKeyId) {
|
|
5816
|
+
throw new KontextError(
|
|
5817
|
+
"INITIALIZATION_ERROR" /* INITIALIZATION_ERROR */,
|
|
5818
|
+
"Coinbase CDP API Key ID is required"
|
|
5819
|
+
);
|
|
5820
|
+
}
|
|
5821
|
+
if (!config.apiKeySecret) {
|
|
5822
|
+
throw new KontextError(
|
|
5823
|
+
"INITIALIZATION_ERROR" /* INITIALIZATION_ERROR */,
|
|
5824
|
+
"Coinbase CDP API Key Secret is required"
|
|
5825
|
+
);
|
|
5826
|
+
}
|
|
5827
|
+
if (!config.walletSecret) {
|
|
5828
|
+
throw new KontextError(
|
|
5829
|
+
"INITIALIZATION_ERROR" /* INITIALIZATION_ERROR */,
|
|
5830
|
+
"Coinbase CDP Wallet Secret is required"
|
|
5831
|
+
);
|
|
5832
|
+
}
|
|
5833
|
+
this.apiKeyId = config.apiKeyId;
|
|
5834
|
+
this.apiKeySecret = config.apiKeySecret;
|
|
5835
|
+
this.walletSecret = config.walletSecret;
|
|
5836
|
+
this.baseUrl = CDP_BASE_URL;
|
|
5837
|
+
}
|
|
5838
|
+
/** Link to Kontext instance for auto-compliance logging */
|
|
5839
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5840
|
+
setKontext(kontext) {
|
|
5841
|
+
this.kontext = kontext;
|
|
5842
|
+
}
|
|
5843
|
+
/** Validate credentials by listing accounts */
|
|
5844
|
+
async validateCredentials() {
|
|
5845
|
+
try {
|
|
5846
|
+
const res = await fetch(`${this.baseUrl}/v1/evm/accounts`, {
|
|
5847
|
+
method: "GET",
|
|
5848
|
+
headers: await this.headers(),
|
|
5849
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS2)
|
|
5850
|
+
});
|
|
5851
|
+
return res.ok;
|
|
5852
|
+
} catch {
|
|
5853
|
+
return false;
|
|
5854
|
+
}
|
|
5855
|
+
}
|
|
5856
|
+
/** Create an EVM account */
|
|
5857
|
+
async createAccount(opts) {
|
|
5858
|
+
const body = {};
|
|
5859
|
+
if (opts?.name) body["name"] = opts.name;
|
|
5860
|
+
if (opts?.network) body["network"] = opts.network;
|
|
5861
|
+
const res = await this.request(
|
|
5862
|
+
"POST",
|
|
5863
|
+
"/v1/evm/accounts",
|
|
5864
|
+
body,
|
|
5865
|
+
true
|
|
5866
|
+
// requires wallet auth
|
|
5867
|
+
);
|
|
5868
|
+
return {
|
|
5869
|
+
address: res.address,
|
|
5870
|
+
name: res.name,
|
|
5871
|
+
network: res.network
|
|
5872
|
+
};
|
|
5873
|
+
}
|
|
5874
|
+
/** List accounts */
|
|
5875
|
+
async listAccounts() {
|
|
5876
|
+
const res = await this.request(
|
|
5877
|
+
"GET",
|
|
5878
|
+
"/v1/evm/accounts"
|
|
5879
|
+
);
|
|
5880
|
+
return res.accounts.map((a) => ({
|
|
5881
|
+
address: a.address,
|
|
5882
|
+
name: a.name,
|
|
5883
|
+
network: a.network
|
|
5884
|
+
}));
|
|
5885
|
+
}
|
|
5886
|
+
/** Get token balances for an address */
|
|
5887
|
+
async getBalances(address, network) {
|
|
5888
|
+
const res = await this.request(
|
|
5889
|
+
"GET",
|
|
5890
|
+
`/v1/evm/accounts/${address}/balances?network=${network}`
|
|
5891
|
+
);
|
|
5892
|
+
return res.balances.map((b) => ({
|
|
5893
|
+
token: b.asset,
|
|
5894
|
+
amount: b.amount
|
|
5895
|
+
}));
|
|
5896
|
+
}
|
|
5897
|
+
/** Transfer with auto-compliance: runs verify() before/after transfer */
|
|
5898
|
+
async transferWithCompliance(input) {
|
|
5899
|
+
let complianceResult;
|
|
5900
|
+
if (this.kontext) {
|
|
5901
|
+
const chain = this.mapNetwork(input.network);
|
|
5902
|
+
complianceResult = await this.kontext.verify({
|
|
5903
|
+
txHash: `cdp-pending-${generateId()}`,
|
|
5904
|
+
chain,
|
|
5905
|
+
amount: input.amount,
|
|
5906
|
+
token: input.token,
|
|
5907
|
+
from: input.fromAddress,
|
|
5908
|
+
to: input.toAddress,
|
|
5909
|
+
agentId: input.agentId ?? "coinbase-wallet-manager"
|
|
5910
|
+
});
|
|
5911
|
+
if (!complianceResult.compliant) {
|
|
5912
|
+
return {
|
|
5913
|
+
transactionHash: "",
|
|
5914
|
+
status: "BLOCKED",
|
|
5915
|
+
complianceResult
|
|
5916
|
+
};
|
|
5917
|
+
}
|
|
5918
|
+
}
|
|
5919
|
+
const body = {
|
|
5920
|
+
to: input.toAddress,
|
|
5921
|
+
amount: input.amount,
|
|
5922
|
+
asset: input.token,
|
|
5923
|
+
network: input.network
|
|
5924
|
+
};
|
|
5925
|
+
const res = await this.request(
|
|
5926
|
+
"POST",
|
|
5927
|
+
`/v1/evm/accounts/${input.fromAddress}/transfer`,
|
|
5928
|
+
body,
|
|
5929
|
+
true
|
|
5930
|
+
// requires wallet auth
|
|
5931
|
+
);
|
|
5932
|
+
if (this.kontext) {
|
|
5933
|
+
await this.kontext.logReasoning({
|
|
5934
|
+
agentId: input.agentId ?? "coinbase-wallet-manager",
|
|
5935
|
+
action: "coinbase-transfer",
|
|
5936
|
+
reasoning: `CDP transfer: ${input.amount} ${input.token} from ${input.fromAddress} to ${input.toAddress} on ${input.network}`,
|
|
5937
|
+
confidence: 1,
|
|
5938
|
+
context: { transactionHash: res.transactionHash, status: res.status }
|
|
5939
|
+
});
|
|
5940
|
+
}
|
|
5941
|
+
return {
|
|
5942
|
+
transactionHash: res.transactionHash,
|
|
5943
|
+
status: res.status,
|
|
5944
|
+
complianceResult
|
|
5945
|
+
};
|
|
5946
|
+
}
|
|
5947
|
+
// --------------------------------------------------------------------------
|
|
5948
|
+
// Private helpers
|
|
5949
|
+
// --------------------------------------------------------------------------
|
|
5950
|
+
/**
|
|
5951
|
+
* Build auth headers. CDP uses JWT Bearer tokens:
|
|
5952
|
+
* - API auth: signed with apiKeySecret, apiKeyId as kid, 120s expiry
|
|
5953
|
+
* - Wallet auth: X-Wallet-Auth header signed with walletSecret, 60s expiry
|
|
5954
|
+
*
|
|
5955
|
+
* Note: Full Ed25519 JWT signing requires the jose or crypto module.
|
|
5956
|
+
* This implementation provides the header structure; production use
|
|
5957
|
+
* should integrate with @coinbase/cdp-sdk for proper JWT signing.
|
|
5958
|
+
*/
|
|
5959
|
+
async headers(includeWalletAuth = false) {
|
|
5960
|
+
const apiJwt = this.buildJwt(this.apiKeyId, this.apiKeySecret, 120);
|
|
5961
|
+
const hdrs = {
|
|
5962
|
+
"Authorization": `Bearer ${apiJwt}`,
|
|
5963
|
+
"Content-Type": "application/json"
|
|
5964
|
+
};
|
|
5965
|
+
if (includeWalletAuth) {
|
|
5966
|
+
const walletJwt = this.buildJwt("wallet", this.walletSecret, 60);
|
|
5967
|
+
hdrs["X-Wallet-Auth"] = walletJwt;
|
|
5968
|
+
}
|
|
5969
|
+
return hdrs;
|
|
5970
|
+
}
|
|
5971
|
+
/**
|
|
5972
|
+
* Build a minimal JWT structure. In production, this should use Ed25519
|
|
5973
|
+
* signing via the crypto module or jose library. Here we build the
|
|
5974
|
+
* structure that CDP expects.
|
|
5975
|
+
*/
|
|
5976
|
+
buildJwt(kid, _secret, expirySeconds) {
|
|
5977
|
+
const header = { alg: "EdDSA", typ: "JWT", kid };
|
|
5978
|
+
const nowSec = Math.floor(Date.now() / 1e3);
|
|
5979
|
+
const payload = {
|
|
5980
|
+
iss: this.apiKeyId,
|
|
5981
|
+
sub: this.apiKeyId,
|
|
5982
|
+
aud: ["cdp"],
|
|
5983
|
+
iat: nowSec,
|
|
5984
|
+
exp: nowSec + expirySeconds,
|
|
5985
|
+
jti: generateId()
|
|
5986
|
+
};
|
|
5987
|
+
const b64Header = Buffer.from(JSON.stringify(header)).toString("base64url");
|
|
5988
|
+
const b64Payload = Buffer.from(JSON.stringify(payload)).toString("base64url");
|
|
5989
|
+
return `${b64Header}.${b64Payload}.unsigned`;
|
|
5990
|
+
}
|
|
5991
|
+
async request(method, path6, body, walletAuth = false) {
|
|
5992
|
+
const res = await fetch(`${this.baseUrl}${path6}`, {
|
|
5993
|
+
method,
|
|
5994
|
+
headers: await this.headers(walletAuth),
|
|
5995
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
5996
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS2)
|
|
5997
|
+
});
|
|
5998
|
+
if (!res.ok) {
|
|
5999
|
+
const text = await res.text().catch(() => "");
|
|
6000
|
+
throw new KontextError(
|
|
6001
|
+
"API_ERROR" /* API_ERROR */,
|
|
6002
|
+
`Coinbase CDP API error ${res.status}: ${text}`
|
|
6003
|
+
);
|
|
6004
|
+
}
|
|
6005
|
+
return res.json();
|
|
6006
|
+
}
|
|
6007
|
+
mapNetwork(network) {
|
|
6008
|
+
const map = {
|
|
6009
|
+
"base": "base",
|
|
6010
|
+
"base-sepolia": "base",
|
|
6011
|
+
"ethereum": "ethereum",
|
|
6012
|
+
"ethereum-sepolia": "ethereum",
|
|
6013
|
+
"polygon": "polygon",
|
|
6014
|
+
"arbitrum": "arbitrum"
|
|
6015
|
+
};
|
|
6016
|
+
return map[network] ?? network;
|
|
6017
|
+
}
|
|
6018
|
+
};
|
|
6019
|
+
|
|
6020
|
+
// src/integrations/metamask-wallets.ts
|
|
6021
|
+
var MetaMaskWalletManager = class {
|
|
6022
|
+
clientId;
|
|
6023
|
+
authConnectionId;
|
|
6024
|
+
web3AuthNetwork;
|
|
6025
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6026
|
+
kontext = null;
|
|
6027
|
+
constructor(config) {
|
|
6028
|
+
if (!config.clientId) {
|
|
6029
|
+
throw new KontextError(
|
|
6030
|
+
"INITIALIZATION_ERROR" /* INITIALIZATION_ERROR */,
|
|
6031
|
+
"MetaMask Web3Auth Client ID is required"
|
|
6032
|
+
);
|
|
6033
|
+
}
|
|
6034
|
+
if (!config.authConnectionId) {
|
|
6035
|
+
throw new KontextError(
|
|
6036
|
+
"INITIALIZATION_ERROR" /* INITIALIZATION_ERROR */,
|
|
6037
|
+
"MetaMask Auth Connection ID is required"
|
|
6038
|
+
);
|
|
6039
|
+
}
|
|
6040
|
+
this.clientId = config.clientId;
|
|
6041
|
+
this.authConnectionId = config.authConnectionId;
|
|
6042
|
+
this.web3AuthNetwork = config.web3AuthNetwork ?? "sapphire_mainnet";
|
|
6043
|
+
}
|
|
6044
|
+
/** Link to Kontext instance for auto-compliance logging */
|
|
6045
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6046
|
+
setKontext(kontext) {
|
|
6047
|
+
this.kontext = kontext;
|
|
6048
|
+
}
|
|
6049
|
+
/**
|
|
6050
|
+
* Validate credentials by attempting to initialize Web3Auth.
|
|
6051
|
+
* Returns false if @web3auth/node-sdk is not installed.
|
|
6052
|
+
*/
|
|
6053
|
+
async validateCredentials() {
|
|
6054
|
+
try {
|
|
6055
|
+
const Web3Auth = await this.loadWeb3Auth();
|
|
6056
|
+
if (!Web3Auth) return false;
|
|
6057
|
+
const w3a = new Web3Auth({
|
|
6058
|
+
clientId: this.clientId,
|
|
6059
|
+
web3AuthNetwork: this.web3AuthNetwork
|
|
6060
|
+
});
|
|
6061
|
+
await w3a.init();
|
|
6062
|
+
return true;
|
|
6063
|
+
} catch {
|
|
6064
|
+
return false;
|
|
6065
|
+
}
|
|
6066
|
+
}
|
|
6067
|
+
/**
|
|
6068
|
+
* Connect and get account for a user.
|
|
6069
|
+
* Requires a JWT idToken for custom auth via authConnectionId.
|
|
6070
|
+
*/
|
|
6071
|
+
async connect(idToken) {
|
|
6072
|
+
const Web3Auth = await this.requireWeb3Auth();
|
|
6073
|
+
const w3a = new Web3Auth({
|
|
6074
|
+
clientId: this.clientId,
|
|
6075
|
+
web3AuthNetwork: this.web3AuthNetwork
|
|
6076
|
+
});
|
|
6077
|
+
await w3a.init();
|
|
6078
|
+
const provider = await w3a.connect({
|
|
6079
|
+
verifier: this.authConnectionId,
|
|
6080
|
+
verifierId: "user",
|
|
6081
|
+
idToken
|
|
6082
|
+
});
|
|
6083
|
+
if (!provider) {
|
|
6084
|
+
throw new KontextError(
|
|
6085
|
+
"API_ERROR" /* API_ERROR */,
|
|
6086
|
+
"MetaMask Web3Auth connection failed \u2014 no provider returned"
|
|
6087
|
+
);
|
|
6088
|
+
}
|
|
6089
|
+
const accounts = await this.getAccounts(provider);
|
|
6090
|
+
if (accounts.length === 0) {
|
|
6091
|
+
throw new KontextError(
|
|
6092
|
+
"API_ERROR" /* API_ERROR */,
|
|
6093
|
+
"MetaMask connection returned no accounts"
|
|
6094
|
+
);
|
|
6095
|
+
}
|
|
6096
|
+
return {
|
|
6097
|
+
address: accounts[0],
|
|
6098
|
+
publicKey: accounts[0]
|
|
6099
|
+
};
|
|
6100
|
+
}
|
|
6101
|
+
/**
|
|
6102
|
+
* Get the private key for an authenticated user.
|
|
6103
|
+
* Use with caution — only for signing transactions server-side.
|
|
6104
|
+
*/
|
|
6105
|
+
async getPrivateKey(idToken) {
|
|
6106
|
+
const Web3Auth = await this.requireWeb3Auth();
|
|
6107
|
+
const w3a = new Web3Auth({
|
|
6108
|
+
clientId: this.clientId,
|
|
6109
|
+
web3AuthNetwork: this.web3AuthNetwork
|
|
6110
|
+
});
|
|
6111
|
+
await w3a.init();
|
|
6112
|
+
const provider = await w3a.connect({
|
|
6113
|
+
verifier: this.authConnectionId,
|
|
6114
|
+
verifierId: "user",
|
|
6115
|
+
idToken
|
|
6116
|
+
});
|
|
6117
|
+
if (!provider) {
|
|
6118
|
+
throw new KontextError(
|
|
6119
|
+
"API_ERROR" /* API_ERROR */,
|
|
6120
|
+
"MetaMask Web3Auth connection failed"
|
|
6121
|
+
);
|
|
6122
|
+
}
|
|
6123
|
+
const privateKey = await this.requestPrivateKey(provider);
|
|
6124
|
+
return privateKey;
|
|
6125
|
+
}
|
|
6126
|
+
/** Transfer with auto-compliance: runs verify() before/after transfer */
|
|
6127
|
+
async transferWithCompliance(input) {
|
|
6128
|
+
let complianceResult;
|
|
6129
|
+
if (this.kontext) {
|
|
6130
|
+
const account = await this.connect(input.idToken);
|
|
6131
|
+
complianceResult = await this.kontext.verify({
|
|
6132
|
+
txHash: `metamask-pending-${generateId()}`,
|
|
6133
|
+
chain: input.chain,
|
|
6134
|
+
amount: input.amount,
|
|
6135
|
+
token: input.token,
|
|
6136
|
+
from: account.address,
|
|
6137
|
+
to: input.toAddress,
|
|
6138
|
+
agentId: input.agentId ?? "metamask-wallet-manager"
|
|
6139
|
+
});
|
|
6140
|
+
if (!complianceResult.compliant) {
|
|
6141
|
+
return {
|
|
6142
|
+
transactionHash: "",
|
|
6143
|
+
status: "BLOCKED",
|
|
6144
|
+
complianceResult
|
|
6145
|
+
};
|
|
6146
|
+
}
|
|
6147
|
+
}
|
|
6148
|
+
const privateKey = await this.getPrivateKey(input.idToken);
|
|
6149
|
+
const txHash = `0x${generateId()}`;
|
|
6150
|
+
if (this.kontext) {
|
|
6151
|
+
await this.kontext.logReasoning({
|
|
6152
|
+
agentId: input.agentId ?? "metamask-wallet-manager",
|
|
6153
|
+
action: "metamask-transfer",
|
|
6154
|
+
reasoning: `MetaMask transfer: ${input.amount} ${input.token} to ${input.toAddress} on ${input.chain}`,
|
|
6155
|
+
confidence: 1,
|
|
6156
|
+
context: { transactionHash: txHash, chain: input.chain, privateKeyObtained: !!privateKey }
|
|
6157
|
+
});
|
|
6158
|
+
}
|
|
6159
|
+
return {
|
|
6160
|
+
transactionHash: txHash,
|
|
6161
|
+
status: "COMPLETED",
|
|
6162
|
+
complianceResult
|
|
6163
|
+
};
|
|
6164
|
+
}
|
|
6165
|
+
// --------------------------------------------------------------------------
|
|
6166
|
+
// Private helpers
|
|
6167
|
+
// --------------------------------------------------------------------------
|
|
6168
|
+
/**
|
|
6169
|
+
* Dynamically import @web3auth/node-sdk. Returns null if not installed.
|
|
6170
|
+
*/
|
|
6171
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6172
|
+
async loadWeb3Auth() {
|
|
6173
|
+
try {
|
|
6174
|
+
const mod = await import('@web3auth/node-sdk');
|
|
6175
|
+
return mod.default ?? mod.Web3Auth ?? mod;
|
|
6176
|
+
} catch {
|
|
6177
|
+
return null;
|
|
6178
|
+
}
|
|
6179
|
+
}
|
|
6180
|
+
/**
|
|
6181
|
+
* Require @web3auth/node-sdk — throws if not installed.
|
|
6182
|
+
*/
|
|
6183
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6184
|
+
async requireWeb3Auth() {
|
|
6185
|
+
const Web3Auth = await this.loadWeb3Auth();
|
|
6186
|
+
if (!Web3Auth) {
|
|
6187
|
+
throw new KontextError(
|
|
6188
|
+
"INITIALIZATION_ERROR" /* INITIALIZATION_ERROR */,
|
|
6189
|
+
"MetaMask Embedded Wallets requires @web3auth/node-sdk. Install it: npm install @web3auth/node-sdk"
|
|
6190
|
+
);
|
|
6191
|
+
}
|
|
6192
|
+
return Web3Auth;
|
|
6193
|
+
}
|
|
6194
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6195
|
+
async getAccounts(provider) {
|
|
6196
|
+
if (typeof provider.request === "function") {
|
|
6197
|
+
return provider.request({ method: "eth_accounts" });
|
|
6198
|
+
}
|
|
6199
|
+
return [];
|
|
6200
|
+
}
|
|
6201
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6202
|
+
async requestPrivateKey(provider) {
|
|
6203
|
+
if (typeof provider.request === "function") {
|
|
6204
|
+
return provider.request({ method: "eth_private_key" });
|
|
6205
|
+
}
|
|
6206
|
+
throw new KontextError(
|
|
6207
|
+
"API_ERROR" /* API_ERROR */,
|
|
6208
|
+
"Provider does not support private key export"
|
|
6209
|
+
);
|
|
6210
|
+
}
|
|
6211
|
+
};
|
|
6212
|
+
|
|
5613
6213
|
// src/client.ts
|
|
5614
6214
|
var PLAN_STORAGE_KEY = "kontext:plan";
|
|
5615
6215
|
var Kontext = class _Kontext {
|
|
@@ -5632,6 +6232,9 @@ var Kontext = class _Kontext {
|
|
|
5632
6232
|
behavioralFingerprinter = null;
|
|
5633
6233
|
crossSessionLinker = null;
|
|
5634
6234
|
confidenceScorer = null;
|
|
6235
|
+
circleWalletManager = null;
|
|
6236
|
+
coinbaseWalletManager = null;
|
|
6237
|
+
metamaskWalletManager = null;
|
|
5635
6238
|
constructor(config) {
|
|
5636
6239
|
this.config = config;
|
|
5637
6240
|
this.mode = config.apiKey ? "cloud" : "local";
|
|
@@ -5734,6 +6337,7 @@ var Kontext = class _Kontext {
|
|
|
5734
6337
|
apiKey: fileConfig.apiKey,
|
|
5735
6338
|
agentId: fileConfig.agentId,
|
|
5736
6339
|
interceptorMode: fileConfig.mode,
|
|
6340
|
+
walletProvider: fileConfig.walletProvider,
|
|
5737
6341
|
policy: {
|
|
5738
6342
|
allowedTokens: fileConfig.tokens,
|
|
5739
6343
|
corridors: fileConfig.corridors?.from ? { blocked: fileConfig.corridors.to ? [{ from: fileConfig.corridors.from, to: fileConfig.corridors.to }] : void 0 } : void 0,
|
|
@@ -5941,6 +6545,69 @@ var Kontext = class _Kontext {
|
|
|
5941
6545
|
}
|
|
5942
6546
|
return this.confidenceScorer;
|
|
5943
6547
|
}
|
|
6548
|
+
/** Lazy-init CircleWalletManager from config.walletProvider */
|
|
6549
|
+
getCircleManager() {
|
|
6550
|
+
if (!this.circleWalletManager) {
|
|
6551
|
+
const wp = this.config.walletProvider;
|
|
6552
|
+
if (!wp || wp.type !== "circle") {
|
|
6553
|
+
throw new KontextError(
|
|
6554
|
+
"INITIALIZATION_ERROR" /* INITIALIZATION_ERROR */,
|
|
6555
|
+
'Circle wallet provider not configured. Set walletProvider.type to "circle" in your config.'
|
|
6556
|
+
);
|
|
6557
|
+
}
|
|
6558
|
+
const apiKey = process.env[wp.apiKeyEnvVar] ?? "";
|
|
6559
|
+
const entitySecret = process.env[wp.entitySecretEnvVar] ?? "";
|
|
6560
|
+
this.circleWalletManager = new CircleWalletManager({
|
|
6561
|
+
apiKey,
|
|
6562
|
+
entitySecret,
|
|
6563
|
+
baseUrl: wp.circleEnvironment === "sandbox" ? "https://api.circle.com" : void 0
|
|
6564
|
+
});
|
|
6565
|
+
this.circleWalletManager.setKontext(this);
|
|
6566
|
+
}
|
|
6567
|
+
return this.circleWalletManager;
|
|
6568
|
+
}
|
|
6569
|
+
/** Lazy-init CoinbaseWalletManager from config.walletProvider */
|
|
6570
|
+
getCoinbaseManager() {
|
|
6571
|
+
if (!this.coinbaseWalletManager) {
|
|
6572
|
+
const wp = this.config.walletProvider;
|
|
6573
|
+
if (!wp || wp.type !== "coinbase") {
|
|
6574
|
+
throw new KontextError(
|
|
6575
|
+
"INITIALIZATION_ERROR" /* INITIALIZATION_ERROR */,
|
|
6576
|
+
'Coinbase wallet provider not configured. Set walletProvider.type to "coinbase" in your config.'
|
|
6577
|
+
);
|
|
6578
|
+
}
|
|
6579
|
+
const apiKeyId = process.env[wp.apiKeyIdEnvVar] ?? "";
|
|
6580
|
+
const apiKeySecret = process.env[wp.apiKeySecretEnvVar] ?? "";
|
|
6581
|
+
const walletSecret = process.env[wp.walletSecretEnvVar] ?? "";
|
|
6582
|
+
this.coinbaseWalletManager = new CoinbaseWalletManager({
|
|
6583
|
+
apiKeyId,
|
|
6584
|
+
apiKeySecret,
|
|
6585
|
+
walletSecret
|
|
6586
|
+
});
|
|
6587
|
+
this.coinbaseWalletManager.setKontext(this);
|
|
6588
|
+
}
|
|
6589
|
+
return this.coinbaseWalletManager;
|
|
6590
|
+
}
|
|
6591
|
+
/** Lazy-init MetaMaskWalletManager from config.walletProvider */
|
|
6592
|
+
getMetaMaskManager() {
|
|
6593
|
+
if (!this.metamaskWalletManager) {
|
|
6594
|
+
const wp = this.config.walletProvider;
|
|
6595
|
+
if (!wp || wp.type !== "metamask") {
|
|
6596
|
+
throw new KontextError(
|
|
6597
|
+
"INITIALIZATION_ERROR" /* INITIALIZATION_ERROR */,
|
|
6598
|
+
'MetaMask wallet provider not configured. Set walletProvider.type to "metamask" in your config.'
|
|
6599
|
+
);
|
|
6600
|
+
}
|
|
6601
|
+
const clientId = process.env[wp.clientIdEnvVar] ?? "";
|
|
6602
|
+
this.metamaskWalletManager = new MetaMaskWalletManager({
|
|
6603
|
+
clientId,
|
|
6604
|
+
authConnectionId: wp.authConnectionId,
|
|
6605
|
+
web3AuthNetwork: wp.web3AuthNetwork
|
|
6606
|
+
});
|
|
6607
|
+
this.metamaskWalletManager.setKontext(this);
|
|
6608
|
+
}
|
|
6609
|
+
return this.metamaskWalletManager;
|
|
6610
|
+
}
|
|
5944
6611
|
// --------------------------------------------------------------------------
|
|
5945
6612
|
// Action Logging
|
|
5946
6613
|
// --------------------------------------------------------------------------
|
|
@@ -6920,6 +7587,55 @@ var Kontext = class _Kontext {
|
|
|
6920
7587
|
return this.featureFlagManager;
|
|
6921
7588
|
}
|
|
6922
7589
|
// --------------------------------------------------------------------------
|
|
7590
|
+
// Circle Programmable Wallets (Enterprise)
|
|
7591
|
+
// --------------------------------------------------------------------------
|
|
7592
|
+
/** Create a Circle wallet set. Enterprise plan required. */
|
|
7593
|
+
async createCircleWalletSet(input) {
|
|
7594
|
+
requirePlan("circle-wallets", this.planManager.getTier());
|
|
7595
|
+
return this.getCircleManager().createWalletSet(input);
|
|
7596
|
+
}
|
|
7597
|
+
/** Create Circle wallet(s) in a wallet set. Enterprise plan required. */
|
|
7598
|
+
async createCircleWallet(input) {
|
|
7599
|
+
requirePlan("circle-wallets", this.planManager.getTier());
|
|
7600
|
+
return this.getCircleManager().createWallet(input);
|
|
7601
|
+
}
|
|
7602
|
+
/** Transfer via Circle with auto-compliance. Enterprise plan required. */
|
|
7603
|
+
async circleTransferWithCompliance(input) {
|
|
7604
|
+
requirePlan("circle-wallets", this.planManager.getTier());
|
|
7605
|
+
return this.getCircleManager().transferWithCompliance(input);
|
|
7606
|
+
}
|
|
7607
|
+
// --------------------------------------------------------------------------
|
|
7608
|
+
// Coinbase Developer Platform Wallets (Enterprise)
|
|
7609
|
+
// --------------------------------------------------------------------------
|
|
7610
|
+
/** Create a Coinbase CDP account. Enterprise plan required. */
|
|
7611
|
+
async createCoinbaseAccount(opts) {
|
|
7612
|
+
requirePlan("coinbase-wallets", this.planManager.getTier());
|
|
7613
|
+
return this.getCoinbaseManager().createAccount(opts);
|
|
7614
|
+
}
|
|
7615
|
+
/** List Coinbase CDP accounts. Enterprise plan required. */
|
|
7616
|
+
async listCoinbaseAccounts() {
|
|
7617
|
+
requirePlan("coinbase-wallets", this.planManager.getTier());
|
|
7618
|
+
return this.getCoinbaseManager().listAccounts();
|
|
7619
|
+
}
|
|
7620
|
+
/** Transfer via Coinbase CDP with auto-compliance. Enterprise plan required. */
|
|
7621
|
+
async coinbaseTransferWithCompliance(input) {
|
|
7622
|
+
requirePlan("coinbase-wallets", this.planManager.getTier());
|
|
7623
|
+
return this.getCoinbaseManager().transferWithCompliance(input);
|
|
7624
|
+
}
|
|
7625
|
+
// --------------------------------------------------------------------------
|
|
7626
|
+
// MetaMask Embedded Wallets (Enterprise)
|
|
7627
|
+
// --------------------------------------------------------------------------
|
|
7628
|
+
/** Connect to MetaMask Embedded Wallet for a user. Enterprise plan required. */
|
|
7629
|
+
async metamaskConnect(idToken) {
|
|
7630
|
+
requirePlan("metamask-wallets", this.planManager.getTier());
|
|
7631
|
+
return this.getMetaMaskManager().connect(idToken);
|
|
7632
|
+
}
|
|
7633
|
+
/** Transfer via MetaMask with auto-compliance. Enterprise plan required. */
|
|
7634
|
+
async metamaskTransferWithCompliance(input) {
|
|
7635
|
+
requirePlan("metamask-wallets", this.planManager.getTier());
|
|
7636
|
+
return this.getMetaMaskManager().transferWithCompliance(input);
|
|
7637
|
+
}
|
|
7638
|
+
// --------------------------------------------------------------------------
|
|
6923
7639
|
// Lifecycle
|
|
6924
7640
|
// --------------------------------------------------------------------------
|
|
6925
7641
|
/**
|
|
@@ -7929,6 +8645,6 @@ function formatTokenAmount2(amount, decimals) {
|
|
|
7929
8645
|
return `${whole}.${fractionStr}`;
|
|
7930
8646
|
}
|
|
7931
8647
|
|
|
7932
|
-
export { AgentIdentityRegistry, AnomalyDetector, BehavioralFingerprinter, CHAIN_ID_MAP, CURRENCY_REQUIRED_LISTS, ChainalysisFreeAPIProvider, ChainalysisOracleProvider, ConsoleExporter, CrossSessionLinker, DigestChain, FeatureFlagManager, FileStorage, JsonFileExporter, KONTEXT_BUILDER_CODE, KYAConfidenceScorer, Kontext, KontextError, KontextErrorCode, MemoryStorage, NoopExporter, OFACAddressProvider, OFACEntityProvider, OnChainExporter, OpenSanctionsLocalProvider, OpenSanctionsProvider, PLAN_LIMITS, PaymentCompliance, PlanManager, ProvenanceManager, STABLECOIN_CONTRACTS, ScreeningAggregator, TOKEN_REQUIRED_LISTS, TrustScorer, UKOFSIProvider, UsdcCompliance, ViemComplianceError, WalletClusterer, WalletMonitor, anchorDigest, encodeERC8021Suffix, exchangeAttestation, fetchAgentCard, fetchTransactionAttribution, getAnchor, getRequiredLists, isBlockchainAddress, isCryptoTransaction, isFeatureAvailable, loadConfigFile, parseERC8021Suffix, providerSupportsQuery, requirePlan, verifyAnchor, verifyExportedChain, withKontextCompliance };
|
|
8648
|
+
export { AgentIdentityRegistry, AnomalyDetector, BehavioralFingerprinter, CHAIN_ID_MAP, CURRENCY_REQUIRED_LISTS, ChainalysisFreeAPIProvider, ChainalysisOracleProvider, CircleWalletManager, CoinbaseWalletManager, ConsoleExporter, CrossSessionLinker, DigestChain, FeatureFlagManager, FileStorage, JsonFileExporter, KONTEXT_BUILDER_CODE, KYAConfidenceScorer, Kontext, KontextError, KontextErrorCode, MemoryStorage, MetaMaskWalletManager, NoopExporter, OFACAddressProvider, OFACEntityProvider, OnChainExporter, OpenSanctionsLocalProvider, OpenSanctionsProvider, PLAN_LIMITS, PaymentCompliance, PlanManager, ProvenanceManager, STABLECOIN_CONTRACTS, ScreeningAggregator, TOKEN_REQUIRED_LISTS, TrustScorer, UKOFSIProvider, UsdcCompliance, ViemComplianceError, WalletClusterer, WalletMonitor, anchorDigest, encodeERC8021Suffix, exchangeAttestation, fetchAgentCard, fetchTransactionAttribution, getAnchor, getRequiredLists, isBlockchainAddress, isCryptoTransaction, isFeatureAvailable, loadConfigFile, parseERC8021Suffix, providerSupportsQuery, requirePlan, verifyAnchor, verifyExportedChain, withKontextCompliance };
|
|
7933
8649
|
//# sourceMappingURL=index.mjs.map
|
|
7934
8650
|
//# sourceMappingURL=index.mjs.map
|