-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathseller.ts
116 lines (100 loc) · 4.1 KB
/
seller.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import dotenv from "dotenv";
dotenv.config();
import {Logger, MetalService, SymbolService} from "metal-on-symbol";
import assert from "assert";
import init, { exchange } from "simple-exchange-wasm/simple_exchange_wasm.js";
import {SmartTransactionService} from "./services/index.js";
import {Account, AggregateTransaction, Deadline, Transaction, TransactionType, TransferTransaction} from "symbol-sdk";
assert(process.env.SELLER_PRIVATE_KEY);
const sellerPrivateKey = process.env.SELLER_PRIVATE_KEY;
assert(process.env.NODE_URL);
const symbolService = new SymbolService({ node_url: process.env.NODE_URL });
const metalService = new MetalService(symbolService);
Logger.init({ log_level: Logger.LogLevel.DEBUG });
const parseCallTxPayload = (payload: string) => {
try {
const callTxPayload = JSON.parse(payload);
if (!SmartTransactionService.isCallTransactionPayload(callTxPayload)) {
return undefined;
}
return callTxPayload;
} catch (e) {
return undefined;
}
};
const handleCallerTx = async (account: Account, tx: TransferTransaction) => {
try {
const callTxPayload = parseCallTxPayload(tx.message.payload);
if (!callTxPayload) {
return;
}
console.log(`Call transaction received: ${tx.message.payload}`)
// Fetch smart transaction
console.log(`Loading smart transaction from Metal: ${callTxPayload.metal_id}`);
const smartTx = await metalService.fetchByMetalId(callTxPayload.metal_id);
// Check smart transaction ownership
if (!smartTx.targetAddress.equals(account.address)) {
console.error(`${callTxPayload.metal_id}: Not owned smart transaction.`);
return;
}
// Init smart transaction
const smartTxService = new SmartTransactionService(
symbolService,
account,
callTxPayload.metal_id,
smartTx.targetAddress,
Deadline.createFromAdjustedValue(callTxPayload.deadline),
);
global.symbolLibrary = smartTxService;
// Execute smart transaction
console.log("Executing smart transaction.");
await init(smartTx.payload);
const result = await exchange(callTxPayload.call_data.arguments[0], callTxPayload.call_data.arguments[1]);
if (!result) {
console.error("Smart transaction execution failed.");
return;
}
// Cosign and announce transaction
console.log("Validating and fulfilling call of smart transaction.");
await smartTxService.fulfill(callTxPayload);
console.log("Handling of call transaction completed.");
} catch (e) {
console.error(e);
}
};
const main = async () => {
const { networkType, repositoryFactory } = await symbolService.getNetwork();
const sellerAccount = Account.createFromPrivateKey(sellerPrivateKey, networkType);
const isTransferTransaction =
(tx: Transaction): tx is TransferTransaction => tx.type === TransactionType.TRANSFER;
const isAggregateCompleteTransaction =
(tx: Transaction): tx is AggregateTransaction => tx.type === TransactionType.AGGREGATE_COMPLETE;
// Listen call transaction
console.log("Starting call transaction listener.");
const listener = repositoryFactory.createListener();
await listener.open();
return new Promise(() => {
listener.confirmed(sellerAccount.address)
.subscribe({
next: async (fetchedTx) => {
const innerTxs = isAggregateCompleteTransaction(fetchedTx)
? fetchedTx.innerTransactions
: [ fetchedTx ];
for (const tx of innerTxs) {
if (!isTransferTransaction(tx)) {
continue;
}
await handleCallerTx(sellerAccount, tx);
}
},
error: (e) => {
console.error(e);
}
});
});
};
main()
.catch((e) => {
console.error(e);
process.exit(1);
});