diff --git a/src/index.ts b/src/index.ts
index 769a450..39a2150 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -236,6 +236,9 @@ const renderCurrentMultisigInfo = (): void => {
const formatOrder = (lastOrder: LastOrder): string => {
if (lastOrder.errorMessage) {
if (lastOrder.errorMessage.startsWith('Contract not active')) return ``;
+ if (lastOrder.errorMessage.startsWith('Failed')) {
+ return `
Failed Order #${lastOrder.order.id} — Execution error
`;
+ }
return `Invalid Order #${lastOrder.order.id} — ${lastOrder.errorMessage}
`;
} else {
const isExpired = lastOrder.orderInfo ? (new Date()).getTime() > lastOrder.orderInfo.expiresAt.getTime() : false;
diff --git a/src/multisig/MultisigChecker.ts b/src/multisig/MultisigChecker.ts
index c0e14c8..53b10ab 100644
--- a/src/multisig/MultisigChecker.ts
+++ b/src/multisig/MultisigChecker.ts
@@ -8,7 +8,7 @@ import {
} from "../utils/utils";
import {Address, Cell, Dictionary} from "@ton/core";
import {endParse, Multisig, parseMultisigData} from "./Multisig";
-import {MyNetworkProvider, sendToIndex} from "../utils/MyNetworkProvider";
+import {MyNetworkProvider, sendToIndex, sendToTonApi} from "../utils/MyNetworkProvider";
import {Op} from "./Constants";
import {Order} from "./Order";
import {checkMultisigOrder, MultisigOrderInfo} from "./MultisigOrderChecker";
@@ -78,6 +78,7 @@ const parseNewOrderOutMsg = (outMsg: any) => {
export interface LastOrder {
utime: number,
+ transactionHash: string;
type: 'new' | 'execute' | 'pending' | 'executed';
errorMessage?: string;
order?: {
@@ -224,6 +225,7 @@ export const checkMultisig = async (
lastOrders.push({
utime: tx.now,
+ transactionHash: tx.hash,
type: 'execute',
order: {
address: {
@@ -238,6 +240,7 @@ export const checkMultisig = async (
} catch (e: any) {
lastOrders.push({
utime: tx.now,
+ transactionHash: tx.hash,
type: 'execute',
errorMessage: e.message
})
@@ -280,6 +283,7 @@ export const checkMultisig = async (
lastOrders.push({
utime: tx.now,
+ transactionHash: tx.hash,
type: 'new',
order: {
address: {
@@ -295,6 +299,7 @@ export const checkMultisig = async (
console.log(e);
lastOrders.push({
utime: tx.now,
+ transactionHash: tx.hash,
type: 'new',
errorMessage: 'Invalid new order: ' + e.message
})
@@ -312,6 +317,7 @@ export const checkMultisig = async (
if (!lastOrdersMap[orderId]) {
lastOrdersMap[orderId] = {
utime: lastOrder.utime,
+ transactionHash: lastOrder.transactionHash,
type: lastOrder.type === 'new' ? 'pending' : 'executed',
order: lastOrder.order
}
@@ -325,6 +331,33 @@ export const checkMultisig = async (
lastOrders = Object.values(lastOrdersMap);
+
+ const findFailTx = (tonApiResult: any): boolean => {
+ if (tonApiResult.transaction) {
+ if (tonApiResult.transaction.success === false) {
+ if (tonApiResult.transaction.in_msg.decoded_op_name !== "excess") {
+ return true;
+ }
+ }
+ }
+ if (tonApiResult.children) {
+ for (let child of tonApiResult.children) {
+ if (findFailTx(child)) return true;
+ }
+ }
+ return false;
+ }
+
+ for (const lastOrder of lastOrders) {
+ if (lastOrder.type === 'executed') {
+ const transactionHashHex = Buffer.from(lastOrder.transactionHash, 'base64').toString('hex');
+ const result = await sendToTonApi('traces/' + transactionHashHex, {}, isTestnet);
+ if (findFailTx(result)) {
+ lastOrder.errorMessage = 'Failed';
+ }
+ }
+ }
+
for (const lastOrder of lastOrders) {
if (lastOrder.type === 'pending') {
try {
diff --git a/src/utils/MyNetworkProvider.ts b/src/utils/MyNetworkProvider.ts
index 7f61a3b..1e4b708 100644
--- a/src/utils/MyNetworkProvider.ts
+++ b/src/utils/MyNetworkProvider.ts
@@ -36,6 +36,27 @@ export const sendToIndex = async (method: string, params: any, isTestnet: boolea
return json;
}
+export const sendToTonApi = async (method: string, params: any, isTestnet: boolean) => {
+ const mainnetRpc = 'https://dev.tonapi.io/v2/';
+ const testnetRpc = 'https://testnet.tonapi.io/v2/';
+ const rpc = isTestnet ? testnetRpc : mainnetRpc;
+
+ const headers = {
+ 'Content-Type': 'application/json',
+ 'Authorization': 'Bearer AHIQH4F4Y4XR6UIAAAAOGYUHWOWLUS6ZIPEXSCLAPOMMD6FSNMPUKHCIJHIP52YTU4VKURA'
+ };
+
+ const response = await fetch(rpc + method + '?' + new URLSearchParams(params), {
+ method: 'GET',
+ headers: headers,
+ });
+ const json = await response.json();
+ if (json.error) {
+ throw new Error(json.error);
+ }
+ return json;
+}
+
export class MyNetworkProvider implements ContractProvider {
private contractAddress: Address;
private isTestnet: boolean;