agentsoul-sdk 1.0.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.d.ts +44 -0
- package/dist/index.js +149 -0
- package/dist/src/index.d.ts +44 -0
- package/dist/src/index.js +149 -0
- package/package.json +29 -0
- package/src/index.ts +153 -0
- package/tsconfig.json +13 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
export interface AgentSoulConfig {
|
|
3
|
+
vaultAddress: string;
|
|
4
|
+
endpoint?: string;
|
|
5
|
+
network?: 'testnet' | 'mainnet';
|
|
6
|
+
dailyLimit?: string;
|
|
7
|
+
guardianWallet?: string;
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ValidateTransferParams {
|
|
11
|
+
recipientAddress: string;
|
|
12
|
+
amountEth: number;
|
|
13
|
+
agentId?: string;
|
|
14
|
+
token?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface ValidateResult {
|
|
17
|
+
allowed: boolean;
|
|
18
|
+
status: 'approved' | 'rejected_limit' | 'rejected_allowlist' | 'failed';
|
|
19
|
+
reason?: string;
|
|
20
|
+
message: string;
|
|
21
|
+
todaySpentEth?: number;
|
|
22
|
+
signature?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare class AgentSoul {
|
|
25
|
+
private config;
|
|
26
|
+
private endpoint;
|
|
27
|
+
constructor(config?: Partial<AgentSoulConfig>);
|
|
28
|
+
/**
|
|
29
|
+
* Pre-flight policy verification for AI agent transactions
|
|
30
|
+
* Intercepts and validates against spending limits, allowlists, and shared immune threats.
|
|
31
|
+
*/
|
|
32
|
+
validateTransfer(params: ValidateTransferParams): Promise<ValidateResult>;
|
|
33
|
+
/**
|
|
34
|
+
* Complete safe transaction runner on Robinhood Chain
|
|
35
|
+
* Validates with AgentSoul shield before executing on-chain via ethers.js
|
|
36
|
+
*/
|
|
37
|
+
executeSecureTransfer(wallet: ethers.Wallet, params: ValidateTransferParams): Promise<{
|
|
38
|
+
success: boolean;
|
|
39
|
+
txHash?: string;
|
|
40
|
+
error?: string;
|
|
41
|
+
}>;
|
|
42
|
+
getConfig(): AgentSoulConfig;
|
|
43
|
+
}
|
|
44
|
+
export default AgentSoul;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.AgentSoul = void 0;
|
|
37
|
+
const ethers_1 = require("ethers");
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
class AgentSoul {
|
|
41
|
+
constructor(config) {
|
|
42
|
+
// 1. Auto-load from local agentsoul.config.json if available
|
|
43
|
+
let fileConfig = {};
|
|
44
|
+
const configPath = path.join(process.cwd(), 'agentsoul.config.json');
|
|
45
|
+
if (fs.existsSync(configPath)) {
|
|
46
|
+
try {
|
|
47
|
+
fileConfig = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
console.warn('[AgentSoul] Warning: could not parse local agentsoul.config.json');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
this.config = {
|
|
54
|
+
vaultAddress: config?.vaultAddress || fileConfig.vaultAddress || '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7',
|
|
55
|
+
endpoint: config?.endpoint || fileConfig.endpoint || 'https://agentsoul.tech/api/transfer',
|
|
56
|
+
network: config?.network || fileConfig.network || 'testnet',
|
|
57
|
+
dailyLimit: config?.dailyLimit || fileConfig.dailyLimit || '2.0',
|
|
58
|
+
guardianWallet: config?.guardianWallet || fileConfig.guardianWallet || '',
|
|
59
|
+
apiKey: config?.apiKey || fileConfig.apiKey || '',
|
|
60
|
+
};
|
|
61
|
+
this.endpoint = this.config.endpoint || 'https://agentsoul.tech/api/transfer';
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Pre-flight policy verification for AI agent transactions
|
|
65
|
+
* Intercepts and validates against spending limits, allowlists, and shared immune threats.
|
|
66
|
+
*/
|
|
67
|
+
async validateTransfer(params) {
|
|
68
|
+
try {
|
|
69
|
+
const response = await fetch(this.endpoint, {
|
|
70
|
+
method: 'POST',
|
|
71
|
+
headers: {
|
|
72
|
+
'Content-Type': 'application/json',
|
|
73
|
+
...(this.config.apiKey ? { 'Authorization': `Bearer ${this.config.apiKey}` } : {}),
|
|
74
|
+
},
|
|
75
|
+
body: JSON.stringify({
|
|
76
|
+
ownerAddress: this.config.vaultAddress,
|
|
77
|
+
recipientAddress: params.recipientAddress,
|
|
78
|
+
amountEth: params.amountEth,
|
|
79
|
+
agentId: params.agentId || 'AI-Agent',
|
|
80
|
+
network: this.config.network || 'testnet',
|
|
81
|
+
token: params.token || 'ETH',
|
|
82
|
+
}),
|
|
83
|
+
});
|
|
84
|
+
const data = (await response.json());
|
|
85
|
+
return {
|
|
86
|
+
allowed: data.allowed === true,
|
|
87
|
+
status: data.status || (data.allowed ? 'approved' : 'failed'),
|
|
88
|
+
reason: data.reason,
|
|
89
|
+
message: data.message || (data.allowed ? 'Approved by AgentSoul Protocol' : 'Transaction rejected'),
|
|
90
|
+
todaySpentEth: data.todaySpentEth,
|
|
91
|
+
signature: data.signature,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
// Local failsafe check if backend is unreachable
|
|
96
|
+
const limit = parseFloat(this.config.dailyLimit || '2.0');
|
|
97
|
+
if (params.amountEth > limit) {
|
|
98
|
+
return {
|
|
99
|
+
allowed: false,
|
|
100
|
+
status: 'rejected_limit',
|
|
101
|
+
reason: 'DAILY_LIMIT_EXCEEDED',
|
|
102
|
+
message: `[Failsafe] Transfer ${params.amountEth} ETH exceeds local daily cap ${limit} ETH`,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
allowed: true,
|
|
107
|
+
status: 'approved',
|
|
108
|
+
message: `[Failsafe] Allowed under local cap (${params.amountEth} ETH <= ${limit} ETH)`,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Complete safe transaction runner on Robinhood Chain
|
|
114
|
+
* Validates with AgentSoul shield before executing on-chain via ethers.js
|
|
115
|
+
*/
|
|
116
|
+
async executeSecureTransfer(wallet, params) {
|
|
117
|
+
const check = await this.validateTransfer(params);
|
|
118
|
+
if (!check.allowed) {
|
|
119
|
+
console.error(`🚨 [AgentSoul] Transaction Intercepted & Blocked: ${check.message}`);
|
|
120
|
+
return {
|
|
121
|
+
success: false,
|
|
122
|
+
error: check.message,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
const tx = await wallet.sendTransaction({
|
|
127
|
+
to: params.recipientAddress,
|
|
128
|
+
value: ethers_1.ethers.parseEther(params.amountEth.toString()),
|
|
129
|
+
gasLimit: 200000, // Satisfies Arbitrum Orbit L2 intrinsic gas
|
|
130
|
+
});
|
|
131
|
+
const receipt = await tx.wait();
|
|
132
|
+
return {
|
|
133
|
+
success: true,
|
|
134
|
+
txHash: receipt?.hash || tx.hash,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
catch (txErr) {
|
|
138
|
+
return {
|
|
139
|
+
success: false,
|
|
140
|
+
error: txErr.message || 'On-chain transfer failed',
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
getConfig() {
|
|
145
|
+
return { ...this.config };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
exports.AgentSoul = AgentSoul;
|
|
149
|
+
exports.default = AgentSoul;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
export interface AgentSoulConfig {
|
|
3
|
+
vaultAddress: string;
|
|
4
|
+
endpoint?: string;
|
|
5
|
+
network?: 'testnet' | 'mainnet';
|
|
6
|
+
dailyLimit?: string;
|
|
7
|
+
guardianWallet?: string;
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ValidateTransferParams {
|
|
11
|
+
recipientAddress: string;
|
|
12
|
+
amountEth: number;
|
|
13
|
+
agentId?: string;
|
|
14
|
+
token?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface ValidateResult {
|
|
17
|
+
allowed: boolean;
|
|
18
|
+
status: 'approved' | 'rejected_limit' | 'rejected_allowlist' | 'failed';
|
|
19
|
+
reason?: string;
|
|
20
|
+
message: string;
|
|
21
|
+
todaySpentEth?: number;
|
|
22
|
+
signature?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare class AgentSoul {
|
|
25
|
+
private config;
|
|
26
|
+
private endpoint;
|
|
27
|
+
constructor(config?: Partial<AgentSoulConfig>);
|
|
28
|
+
/**
|
|
29
|
+
* Pre-flight policy verification for AI agent transactions
|
|
30
|
+
* Intercepts and validates against spending limits, allowlists, and shared immune threats.
|
|
31
|
+
*/
|
|
32
|
+
validateTransfer(params: ValidateTransferParams): Promise<ValidateResult>;
|
|
33
|
+
/**
|
|
34
|
+
* Complete safe transaction runner on Robinhood Chain
|
|
35
|
+
* Validates with AgentSoul shield before executing on-chain via ethers.js
|
|
36
|
+
*/
|
|
37
|
+
executeSecureTransfer(wallet: ethers.Wallet, params: ValidateTransferParams): Promise<{
|
|
38
|
+
success: boolean;
|
|
39
|
+
txHash?: string;
|
|
40
|
+
error?: string;
|
|
41
|
+
}>;
|
|
42
|
+
getConfig(): AgentSoulConfig;
|
|
43
|
+
}
|
|
44
|
+
export default AgentSoul;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.AgentSoul = void 0;
|
|
37
|
+
const ethers_1 = require("ethers");
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
class AgentSoul {
|
|
41
|
+
constructor(config) {
|
|
42
|
+
// 1. Auto-load from local agentsoul.config.json if available
|
|
43
|
+
let fileConfig = {};
|
|
44
|
+
const configPath = path.join(process.cwd(), 'agentsoul.config.json');
|
|
45
|
+
if (fs.existsSync(configPath)) {
|
|
46
|
+
try {
|
|
47
|
+
fileConfig = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
console.warn('[AgentSoul] Warning: could not parse local agentsoul.config.json');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
this.config = {
|
|
54
|
+
vaultAddress: config?.vaultAddress || fileConfig.vaultAddress || '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7',
|
|
55
|
+
endpoint: config?.endpoint || fileConfig.endpoint || 'https://agentsoul.tech/api/transfer',
|
|
56
|
+
network: config?.network || fileConfig.network || 'testnet',
|
|
57
|
+
dailyLimit: config?.dailyLimit || fileConfig.dailyLimit || '2.0',
|
|
58
|
+
guardianWallet: config?.guardianWallet || fileConfig.guardianWallet || '',
|
|
59
|
+
apiKey: config?.apiKey || fileConfig.apiKey || '',
|
|
60
|
+
};
|
|
61
|
+
this.endpoint = this.config.endpoint || 'https://agentsoul.tech/api/transfer';
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Pre-flight policy verification for AI agent transactions
|
|
65
|
+
* Intercepts and validates against spending limits, allowlists, and shared immune threats.
|
|
66
|
+
*/
|
|
67
|
+
async validateTransfer(params) {
|
|
68
|
+
try {
|
|
69
|
+
const response = await fetch(this.endpoint, {
|
|
70
|
+
method: 'POST',
|
|
71
|
+
headers: {
|
|
72
|
+
'Content-Type': 'application/json',
|
|
73
|
+
...(this.config.apiKey ? { 'Authorization': `Bearer ${this.config.apiKey}` } : {}),
|
|
74
|
+
},
|
|
75
|
+
body: JSON.stringify({
|
|
76
|
+
ownerAddress: this.config.vaultAddress,
|
|
77
|
+
recipientAddress: params.recipientAddress,
|
|
78
|
+
amountEth: params.amountEth,
|
|
79
|
+
agentId: params.agentId || 'AI-Agent',
|
|
80
|
+
network: this.config.network || 'testnet',
|
|
81
|
+
token: params.token || 'ETH',
|
|
82
|
+
}),
|
|
83
|
+
});
|
|
84
|
+
const data = (await response.json());
|
|
85
|
+
return {
|
|
86
|
+
allowed: data.allowed === true,
|
|
87
|
+
status: data.status || (data.allowed ? 'approved' : 'failed'),
|
|
88
|
+
reason: data.reason,
|
|
89
|
+
message: data.message || (data.allowed ? 'Approved by AgentSoul Protocol' : 'Transaction rejected'),
|
|
90
|
+
todaySpentEth: data.todaySpentEth,
|
|
91
|
+
signature: data.signature,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
// Local failsafe check if backend is unreachable
|
|
96
|
+
const limit = parseFloat(this.config.dailyLimit || '2.0');
|
|
97
|
+
if (params.amountEth > limit) {
|
|
98
|
+
return {
|
|
99
|
+
allowed: false,
|
|
100
|
+
status: 'rejected_limit',
|
|
101
|
+
reason: 'DAILY_LIMIT_EXCEEDED',
|
|
102
|
+
message: `[Failsafe] Transfer ${params.amountEth} ETH exceeds local daily cap ${limit} ETH`,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
allowed: true,
|
|
107
|
+
status: 'approved',
|
|
108
|
+
message: `[Failsafe] Allowed under local cap (${params.amountEth} ETH <= ${limit} ETH)`,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Complete safe transaction runner on Robinhood Chain
|
|
114
|
+
* Validates with AgentSoul shield before executing on-chain via ethers.js
|
|
115
|
+
*/
|
|
116
|
+
async executeSecureTransfer(wallet, params) {
|
|
117
|
+
const check = await this.validateTransfer(params);
|
|
118
|
+
if (!check.allowed) {
|
|
119
|
+
console.error(`🚨 [AgentSoul] Transaction Intercepted & Blocked: ${check.message}`);
|
|
120
|
+
return {
|
|
121
|
+
success: false,
|
|
122
|
+
error: check.message,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
const tx = await wallet.sendTransaction({
|
|
127
|
+
to: params.recipientAddress,
|
|
128
|
+
value: ethers_1.ethers.parseEther(params.amountEth.toString()),
|
|
129
|
+
gasLimit: 200000, // Satisfies Arbitrum Orbit L2 intrinsic gas
|
|
130
|
+
});
|
|
131
|
+
const receipt = await tx.wait();
|
|
132
|
+
return {
|
|
133
|
+
success: true,
|
|
134
|
+
txHash: receipt?.hash || tx.hash,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
catch (txErr) {
|
|
138
|
+
return {
|
|
139
|
+
success: false,
|
|
140
|
+
error: txErr.message || 'On-chain transfer failed',
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
getConfig() {
|
|
145
|
+
return { ...this.config };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
exports.AgentSoul = AgentSoul;
|
|
149
|
+
exports.default = AgentSoul;
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agentsoul-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Production Security SDK for Autonomous AI Agents on Robinhood Chain",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"agentsoul",
|
|
13
|
+
"ai-agents",
|
|
14
|
+
"elizaos",
|
|
15
|
+
"robinhood-chain",
|
|
16
|
+
"security",
|
|
17
|
+
"anti-drain",
|
|
18
|
+
"blockchain",
|
|
19
|
+
"evm"
|
|
20
|
+
],
|
|
21
|
+
"author": "AgentSoul Protocol <titershield@gmail.com>",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"ethers": "^6.13.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"typescript": "^5.0.0"
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
|
|
5
|
+
export interface AgentSoulConfig {
|
|
6
|
+
vaultAddress: string;
|
|
7
|
+
endpoint?: string;
|
|
8
|
+
network?: 'testnet' | 'mainnet';
|
|
9
|
+
dailyLimit?: string;
|
|
10
|
+
guardianWallet?: string;
|
|
11
|
+
apiKey?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface ValidateTransferParams {
|
|
15
|
+
recipientAddress: string;
|
|
16
|
+
amountEth: number;
|
|
17
|
+
agentId?: string;
|
|
18
|
+
token?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ValidateResult {
|
|
22
|
+
allowed: boolean;
|
|
23
|
+
status: 'approved' | 'rejected_limit' | 'rejected_allowlist' | 'failed';
|
|
24
|
+
reason?: string;
|
|
25
|
+
message: string;
|
|
26
|
+
todaySpentEth?: number;
|
|
27
|
+
signature?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class AgentSoul {
|
|
31
|
+
private config: AgentSoulConfig;
|
|
32
|
+
private endpoint: string;
|
|
33
|
+
|
|
34
|
+
constructor(config?: Partial<AgentSoulConfig>) {
|
|
35
|
+
// 1. Auto-load from local agentsoul.config.json if available
|
|
36
|
+
let fileConfig: Partial<AgentSoulConfig> = {};
|
|
37
|
+
const configPath = path.join(process.cwd(), 'agentsoul.config.json');
|
|
38
|
+
if (fs.existsSync(configPath)) {
|
|
39
|
+
try {
|
|
40
|
+
fileConfig = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
41
|
+
} catch (err) {
|
|
42
|
+
console.warn('[AgentSoul] Warning: could not parse local agentsoul.config.json');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
this.config = {
|
|
47
|
+
vaultAddress: config?.vaultAddress || fileConfig.vaultAddress || '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7',
|
|
48
|
+
endpoint: config?.endpoint || fileConfig.endpoint || 'https://agentsoul.tech/api/transfer',
|
|
49
|
+
network: config?.network || fileConfig.network || 'testnet',
|
|
50
|
+
dailyLimit: config?.dailyLimit || fileConfig.dailyLimit || '2.0',
|
|
51
|
+
guardianWallet: config?.guardianWallet || fileConfig.guardianWallet || '',
|
|
52
|
+
apiKey: config?.apiKey || fileConfig.apiKey || '',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
this.endpoint = this.config.endpoint || 'https://agentsoul.tech/api/transfer';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Pre-flight policy verification for AI agent transactions
|
|
60
|
+
* Intercepts and validates against spending limits, allowlists, and shared immune threats.
|
|
61
|
+
*/
|
|
62
|
+
public async validateTransfer(params: ValidateTransferParams): Promise<ValidateResult> {
|
|
63
|
+
try {
|
|
64
|
+
const response = await fetch(this.endpoint, {
|
|
65
|
+
method: 'POST',
|
|
66
|
+
headers: {
|
|
67
|
+
'Content-Type': 'application/json',
|
|
68
|
+
...(this.config.apiKey ? { 'Authorization': `Bearer ${this.config.apiKey}` } : {}),
|
|
69
|
+
},
|
|
70
|
+
body: JSON.stringify({
|
|
71
|
+
ownerAddress: this.config.vaultAddress,
|
|
72
|
+
recipientAddress: params.recipientAddress,
|
|
73
|
+
amountEth: params.amountEth,
|
|
74
|
+
agentId: params.agentId || 'AI-Agent',
|
|
75
|
+
network: this.config.network || 'testnet',
|
|
76
|
+
token: params.token || 'ETH',
|
|
77
|
+
}),
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const data = (await response.json()) as any;
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
allowed: data.allowed === true,
|
|
84
|
+
status: data.status || (data.allowed ? 'approved' : 'failed'),
|
|
85
|
+
reason: data.reason,
|
|
86
|
+
message: data.message || (data.allowed ? 'Approved by AgentSoul Protocol' : 'Transaction rejected'),
|
|
87
|
+
todaySpentEth: data.todaySpentEth,
|
|
88
|
+
signature: data.signature,
|
|
89
|
+
};
|
|
90
|
+
} catch (error: any) {
|
|
91
|
+
// Local failsafe check if backend is unreachable
|
|
92
|
+
const limit = parseFloat(this.config.dailyLimit || '2.0');
|
|
93
|
+
if (params.amountEth > limit) {
|
|
94
|
+
return {
|
|
95
|
+
allowed: false,
|
|
96
|
+
status: 'rejected_limit',
|
|
97
|
+
reason: 'DAILY_LIMIT_EXCEEDED',
|
|
98
|
+
message: `[Failsafe] Transfer ${params.amountEth} ETH exceeds local daily cap ${limit} ETH`,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
allowed: true,
|
|
104
|
+
status: 'approved',
|
|
105
|
+
message: `[Failsafe] Allowed under local cap (${params.amountEth} ETH <= ${limit} ETH)`,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Complete safe transaction runner on Robinhood Chain
|
|
112
|
+
* Validates with AgentSoul shield before executing on-chain via ethers.js
|
|
113
|
+
*/
|
|
114
|
+
public async executeSecureTransfer(
|
|
115
|
+
wallet: ethers.Wallet,
|
|
116
|
+
params: ValidateTransferParams
|
|
117
|
+
): Promise<{ success: boolean; txHash?: string; error?: string }> {
|
|
118
|
+
const check = await this.validateTransfer(params);
|
|
119
|
+
|
|
120
|
+
if (!check.allowed) {
|
|
121
|
+
console.error(`🚨 [AgentSoul] Transaction Intercepted & Blocked: ${check.message}`);
|
|
122
|
+
return {
|
|
123
|
+
success: false,
|
|
124
|
+
error: check.message,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
const tx = await wallet.sendTransaction({
|
|
130
|
+
to: params.recipientAddress,
|
|
131
|
+
value: ethers.parseEther(params.amountEth.toString()),
|
|
132
|
+
gasLimit: 200000, // Satisfies Arbitrum Orbit L2 intrinsic gas
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const receipt = await tx.wait();
|
|
136
|
+
return {
|
|
137
|
+
success: true,
|
|
138
|
+
txHash: receipt?.hash || tx.hash,
|
|
139
|
+
};
|
|
140
|
+
} catch (txErr: any) {
|
|
141
|
+
return {
|
|
142
|
+
success: false,
|
|
143
|
+
error: txErr.message || 'On-chain transfer failed',
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
public getConfig(): AgentSoulConfig {
|
|
149
|
+
return { ...this.config };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export default AgentSoul;
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"declaration": true,
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true
|
|
11
|
+
},
|
|
12
|
+
"include": ["src/**/*"]
|
|
13
|
+
}
|