@ton-agent-kit/plugin-escrow 1.2.0 → 1.2.1
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/package.json +1 -1
- package/src/utils.ts +168 -168
package/package.json
CHANGED
package/src/utils.ts
CHANGED
|
@@ -1,168 +1,168 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
2
|
-
import { Address, internal, toNano, beginCell } from "@ton/core";
|
|
3
|
-
import { TonClient4 } from "@ton/ton";
|
|
4
|
-
import type { AgentContext } from "@ton-agent-kit/core";
|
|
5
|
-
import {
|
|
6
|
-
Escrow,
|
|
7
|
-
storeDeploy,
|
|
8
|
-
storeDeposit,
|
|
9
|
-
storeRelease,
|
|
10
|
-
storeRefund,
|
|
11
|
-
storeDeliveryConfirmed,
|
|
12
|
-
storeAutoRelease,
|
|
13
|
-
storeOpenDispute,
|
|
14
|
-
storeJoinDispute,
|
|
15
|
-
storeVoteRelease,
|
|
16
|
-
storeVoteRefund,
|
|
17
|
-
storeClaimReward,
|
|
18
|
-
storeFallbackSettle,
|
|
19
|
-
storeSellerStake,
|
|
20
|
-
} from "./contracts/Escrow_Escrow";
|
|
21
|
-
import { sendTransaction } from "@ton-agent-kit/core";
|
|
22
|
-
|
|
23
|
-
const ESCROW_FILE = ".escrow-store.json";
|
|
24
|
-
|
|
25
|
-
export interface EscrowRecord {
|
|
26
|
-
id: string;
|
|
27
|
-
contractAddress: string;
|
|
28
|
-
depositor: string;
|
|
29
|
-
beneficiary: string;
|
|
30
|
-
amount: string;
|
|
31
|
-
deadline: number;
|
|
32
|
-
deadlineISO: string;
|
|
33
|
-
minArbiters: number;
|
|
34
|
-
minStake: string;
|
|
35
|
-
description: string;
|
|
36
|
-
status: string;
|
|
37
|
-
createdAt: string;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function loadEscrows(): Record<string, EscrowRecord> {
|
|
41
|
-
try {
|
|
42
|
-
if (existsSync(ESCROW_FILE)) {
|
|
43
|
-
return JSON.parse(readFileSync(ESCROW_FILE, "utf-8"));
|
|
44
|
-
}
|
|
45
|
-
} catch (err: any) {
|
|
46
|
-
console.error(`Failed to load escrow store: ${err.message}`);
|
|
47
|
-
}
|
|
48
|
-
return {};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function saveEscrows(escrows: Record<string, EscrowRecord>): void {
|
|
52
|
-
try {
|
|
53
|
-
writeFileSync(ESCROW_FILE, JSON.stringify(escrows, null, 2), "utf-8");
|
|
54
|
-
} catch (err: any) {
|
|
55
|
-
console.error(`Failed to save escrow store: ${err.message}`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// ── On-chain helpers ──
|
|
60
|
-
|
|
61
|
-
export async function deployEscrowContract(
|
|
62
|
-
agent: AgentContext,
|
|
63
|
-
depositor: Address,
|
|
64
|
-
beneficiary: Address,
|
|
65
|
-
deadline: bigint,
|
|
66
|
-
minArbiters: bigint,
|
|
67
|
-
minStake: bigint,
|
|
68
|
-
reputationContract: Address,
|
|
69
|
-
requireRepCollateral: boolean,
|
|
70
|
-
minRepScore: bigint,
|
|
71
|
-
baseSellerStake: bigint,
|
|
72
|
-
): Promise<Address> {
|
|
73
|
-
const escrow = await Escrow.fromInit(depositor, beneficiary, deadline, minArbiters, minStake, reputationContract, requireRepCollateral, minRepScore, baseSellerStake);
|
|
74
|
-
const deployBody = beginCell()
|
|
75
|
-
.store(storeDeploy({ $$type: "Deploy", queryId: 0n }))
|
|
76
|
-
.endCell();
|
|
77
|
-
|
|
78
|
-
await sendTransaction(agent, [
|
|
79
|
-
internal({
|
|
80
|
-
to: escrow.address,
|
|
81
|
-
value: toNano("0.
|
|
82
|
-
bounce: false,
|
|
83
|
-
init: escrow.init!,
|
|
84
|
-
body: deployBody,
|
|
85
|
-
}),
|
|
86
|
-
]);
|
|
87
|
-
return escrow.address;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export async function depositToContract(agent: AgentContext, contractAddress: Address, amount: string): Promise<void> {
|
|
91
|
-
const body = beginCell().store(storeDeposit({ $$type: "Deposit", queryId: 0n })).endCell();
|
|
92
|
-
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano(amount), bounce: true, body })]);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export async function releaseContract(agent: AgentContext, contractAddress: Address): Promise<void> {
|
|
96
|
-
const body = beginCell().store(storeRelease({ $$type: "Release", queryId: 0n })).endCell();
|
|
97
|
-
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export async function refundContract(agent: AgentContext, contractAddress: Address): Promise<void> {
|
|
101
|
-
const body = beginCell().store(storeRefund({ $$type: "Refund", queryId: 0n })).endCell();
|
|
102
|
-
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export async function confirmDeliveryOnContract(agent: AgentContext, contractAddress: Address, x402TxHash: string): Promise<void> {
|
|
106
|
-
const body = beginCell().store(storeDeliveryConfirmed({ $$type: "DeliveryConfirmed", x402TxHash })).endCell();
|
|
107
|
-
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export async function autoReleaseOnContract(agent: AgentContext, contractAddress: Address): Promise<void> {
|
|
111
|
-
const body = beginCell().store(storeAutoRelease({ $$type: "AutoRelease" })).endCell();
|
|
112
|
-
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export async function openDisputeOnContract(agent: AgentContext, contractAddress: Address): Promise<void> {
|
|
116
|
-
const body = beginCell().store(storeOpenDispute({ $$type: "OpenDispute" })).endCell();
|
|
117
|
-
// 0.
|
|
118
|
-
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export async function joinDisputeOnContract(agent: AgentContext, contractAddress: Address, stakeAmount: string): Promise<void> {
|
|
122
|
-
const body = beginCell().store(storeJoinDispute({ $$type: "JoinDispute" })).endCell();
|
|
123
|
-
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano(stakeAmount), bounce: true, body })]);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export async function voteReleaseOnContract(agent: AgentContext, contractAddress: Address): Promise<void> {
|
|
127
|
-
const body = beginCell().store(storeVoteRelease({ $$type: "VoteRelease" })).endCell();
|
|
128
|
-
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export async function voteRefundOnContract(agent: AgentContext, contractAddress: Address): Promise<void> {
|
|
132
|
-
const body = beginCell().store(storeVoteRefund({ $$type: "VoteRefund" })).endCell();
|
|
133
|
-
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export async function claimRewardOnContract(agent: AgentContext, contractAddress: Address): Promise<void> {
|
|
137
|
-
const body = beginCell().store(storeClaimReward({ $$type: "ClaimReward" })).endCell();
|
|
138
|
-
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export async function fallbackSettleOnContract(agent: AgentContext, contractAddress: Address): Promise<void> {
|
|
142
|
-
const body = beginCell().store(storeFallbackSettle({ $$type: "FallbackSettle" })).endCell();
|
|
143
|
-
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export async function sellerStakeOnContract(agent: AgentContext, contractAddress: Address, stakeAmount: string): Promise<void> {
|
|
147
|
-
const body = beginCell().store(storeSellerStake({ $$type: "SellerStake" })).endCell();
|
|
148
|
-
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano(stakeAmount), bounce: true, body })]);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export async function getContractState(agent: AgentContext, contractAddress: Address) {
|
|
152
|
-
const client = new TonClient4({ endpoint: agent.rpcUrl });
|
|
153
|
-
const contract = client.open(Escrow.fromAddress(contractAddress));
|
|
154
|
-
const data = await contract.getEscrowData();
|
|
155
|
-
const balance = await contract.getBalance();
|
|
156
|
-
return { ...data, balance };
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export async function getLatestTxHash(address: string, network: "testnet" | "mainnet"): Promise<string> {
|
|
160
|
-
const apiBase = network === "testnet" ? "https://testnet.tonapi.io/v2" : "https://tonapi.io/v2";
|
|
161
|
-
try {
|
|
162
|
-
const res = await fetch(`${apiBase}/accounts/${encodeURIComponent(address)}/events?limit=1`);
|
|
163
|
-
const data = await res.json();
|
|
164
|
-
return data.events?.[0]?.event_id || "pending";
|
|
165
|
-
} catch {
|
|
166
|
-
return "pending";
|
|
167
|
-
}
|
|
168
|
-
}
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
2
|
+
import { Address, internal, toNano, beginCell } from "@ton/core";
|
|
3
|
+
import { TonClient4 } from "@ton/ton";
|
|
4
|
+
import type { AgentContext } from "@ton-agent-kit/core";
|
|
5
|
+
import {
|
|
6
|
+
Escrow,
|
|
7
|
+
storeDeploy,
|
|
8
|
+
storeDeposit,
|
|
9
|
+
storeRelease,
|
|
10
|
+
storeRefund,
|
|
11
|
+
storeDeliveryConfirmed,
|
|
12
|
+
storeAutoRelease,
|
|
13
|
+
storeOpenDispute,
|
|
14
|
+
storeJoinDispute,
|
|
15
|
+
storeVoteRelease,
|
|
16
|
+
storeVoteRefund,
|
|
17
|
+
storeClaimReward,
|
|
18
|
+
storeFallbackSettle,
|
|
19
|
+
storeSellerStake,
|
|
20
|
+
} from "./contracts/Escrow_Escrow";
|
|
21
|
+
import { sendTransaction } from "@ton-agent-kit/core";
|
|
22
|
+
|
|
23
|
+
const ESCROW_FILE = ".escrow-store.json";
|
|
24
|
+
|
|
25
|
+
export interface EscrowRecord {
|
|
26
|
+
id: string;
|
|
27
|
+
contractAddress: string;
|
|
28
|
+
depositor: string;
|
|
29
|
+
beneficiary: string;
|
|
30
|
+
amount: string;
|
|
31
|
+
deadline: number;
|
|
32
|
+
deadlineISO: string;
|
|
33
|
+
minArbiters: number;
|
|
34
|
+
minStake: string;
|
|
35
|
+
description: string;
|
|
36
|
+
status: string;
|
|
37
|
+
createdAt: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function loadEscrows(): Record<string, EscrowRecord> {
|
|
41
|
+
try {
|
|
42
|
+
if (existsSync(ESCROW_FILE)) {
|
|
43
|
+
return JSON.parse(readFileSync(ESCROW_FILE, "utf-8"));
|
|
44
|
+
}
|
|
45
|
+
} catch (err: any) {
|
|
46
|
+
console.error(`Failed to load escrow store: ${err.message}`);
|
|
47
|
+
}
|
|
48
|
+
return {};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function saveEscrows(escrows: Record<string, EscrowRecord>): void {
|
|
52
|
+
try {
|
|
53
|
+
writeFileSync(ESCROW_FILE, JSON.stringify(escrows, null, 2), "utf-8");
|
|
54
|
+
} catch (err: any) {
|
|
55
|
+
console.error(`Failed to save escrow store: ${err.message}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ── On-chain helpers ──
|
|
60
|
+
|
|
61
|
+
export async function deployEscrowContract(
|
|
62
|
+
agent: AgentContext,
|
|
63
|
+
depositor: Address,
|
|
64
|
+
beneficiary: Address,
|
|
65
|
+
deadline: bigint,
|
|
66
|
+
minArbiters: bigint,
|
|
67
|
+
minStake: bigint,
|
|
68
|
+
reputationContract: Address,
|
|
69
|
+
requireRepCollateral: boolean,
|
|
70
|
+
minRepScore: bigint,
|
|
71
|
+
baseSellerStake: bigint,
|
|
72
|
+
): Promise<Address> {
|
|
73
|
+
const escrow = await Escrow.fromInit(depositor, beneficiary, deadline, minArbiters, minStake, reputationContract, requireRepCollateral, minRepScore, baseSellerStake);
|
|
74
|
+
const deployBody = beginCell()
|
|
75
|
+
.store(storeDeploy({ $$type: "Deploy", queryId: 0n }))
|
|
76
|
+
.endCell();
|
|
77
|
+
|
|
78
|
+
await sendTransaction(agent, [
|
|
79
|
+
internal({
|
|
80
|
+
to: escrow.address,
|
|
81
|
+
value: toNano("0.12"),
|
|
82
|
+
bounce: false,
|
|
83
|
+
init: escrow.init!,
|
|
84
|
+
body: deployBody,
|
|
85
|
+
}),
|
|
86
|
+
]);
|
|
87
|
+
return escrow.address;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export async function depositToContract(agent: AgentContext, contractAddress: Address, amount: string): Promise<void> {
|
|
91
|
+
const body = beginCell().store(storeDeposit({ $$type: "Deposit", queryId: 0n })).endCell();
|
|
92
|
+
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano(amount), bounce: true, body })]);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export async function releaseContract(agent: AgentContext, contractAddress: Address): Promise<void> {
|
|
96
|
+
const body = beginCell().store(storeRelease({ $$type: "Release", queryId: 0n })).endCell();
|
|
97
|
+
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.12"), bounce: true, body })]);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export async function refundContract(agent: AgentContext, contractAddress: Address): Promise<void> {
|
|
101
|
+
const body = beginCell().store(storeRefund({ $$type: "Refund", queryId: 0n })).endCell();
|
|
102
|
+
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.12"), bounce: true, body })]);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export async function confirmDeliveryOnContract(agent: AgentContext, contractAddress: Address, x402TxHash: string): Promise<void> {
|
|
106
|
+
const body = beginCell().store(storeDeliveryConfirmed({ $$type: "DeliveryConfirmed", x402TxHash })).endCell();
|
|
107
|
+
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.12"), bounce: true, body })]);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export async function autoReleaseOnContract(agent: AgentContext, contractAddress: Address): Promise<void> {
|
|
111
|
+
const body = beginCell().store(storeAutoRelease({ $$type: "AutoRelease" })).endCell();
|
|
112
|
+
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.12"), bounce: true, body })]);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export async function openDisputeOnContract(agent: AgentContext, contractAddress: Address): Promise<void> {
|
|
116
|
+
const body = beginCell().store(storeOpenDispute({ $$type: "OpenDispute" })).endCell();
|
|
117
|
+
// 0.15 TON: escrow gas + cross-contract notification to reputation. Excess refunded.
|
|
118
|
+
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.15"), bounce: true, body })]);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export async function joinDisputeOnContract(agent: AgentContext, contractAddress: Address, stakeAmount: string): Promise<void> {
|
|
122
|
+
const body = beginCell().store(storeJoinDispute({ $$type: "JoinDispute" })).endCell();
|
|
123
|
+
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano(stakeAmount), bounce: true, body })]);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export async function voteReleaseOnContract(agent: AgentContext, contractAddress: Address): Promise<void> {
|
|
127
|
+
const body = beginCell().store(storeVoteRelease({ $$type: "VoteRelease" })).endCell();
|
|
128
|
+
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.12"), bounce: true, body })]);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export async function voteRefundOnContract(agent: AgentContext, contractAddress: Address): Promise<void> {
|
|
132
|
+
const body = beginCell().store(storeVoteRefund({ $$type: "VoteRefund" })).endCell();
|
|
133
|
+
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.12"), bounce: true, body })]);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export async function claimRewardOnContract(agent: AgentContext, contractAddress: Address): Promise<void> {
|
|
137
|
+
const body = beginCell().store(storeClaimReward({ $$type: "ClaimReward" })).endCell();
|
|
138
|
+
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.12"), bounce: true, body })]);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export async function fallbackSettleOnContract(agent: AgentContext, contractAddress: Address): Promise<void> {
|
|
142
|
+
const body = beginCell().store(storeFallbackSettle({ $$type: "FallbackSettle" })).endCell();
|
|
143
|
+
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano("0.12"), bounce: true, body })]);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export async function sellerStakeOnContract(agent: AgentContext, contractAddress: Address, stakeAmount: string): Promise<void> {
|
|
147
|
+
const body = beginCell().store(storeSellerStake({ $$type: "SellerStake" })).endCell();
|
|
148
|
+
await sendTransaction(agent, [internal({ to: contractAddress, value: toNano(stakeAmount), bounce: true, body })]);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export async function getContractState(agent: AgentContext, contractAddress: Address) {
|
|
152
|
+
const client = new TonClient4({ endpoint: agent.rpcUrl });
|
|
153
|
+
const contract = client.open(Escrow.fromAddress(contractAddress));
|
|
154
|
+
const data = await contract.getEscrowData();
|
|
155
|
+
const balance = await contract.getBalance();
|
|
156
|
+
return { ...data, balance };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export async function getLatestTxHash(address: string, network: "testnet" | "mainnet"): Promise<string> {
|
|
160
|
+
const apiBase = network === "testnet" ? "https://testnet.tonapi.io/v2" : "https://tonapi.io/v2";
|
|
161
|
+
try {
|
|
162
|
+
const res = await fetch(`${apiBase}/accounts/${encodeURIComponent(address)}/events?limit=1`);
|
|
163
|
+
const data = await res.json();
|
|
164
|
+
return data.events?.[0]?.event_id || "pending";
|
|
165
|
+
} catch {
|
|
166
|
+
return "pending";
|
|
167
|
+
}
|
|
168
|
+
}
|