Skip to content
This repository was archived by the owner on Feb 8, 2025. It is now read-only.

Commit 9d44b40

Browse files
authored
Merge pull request #283 from zallo-labs/improved-status
Improved-status
2 parents 3165f9e + f551d0c commit 9d44b40

8 files changed

+71
-29
lines changed

api/dbschema/edgeql-js/__spec__.ts

+2-2
Large diffs are not rendered by default.

api/dbschema/edgeql-js/modules/default.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,7 @@ const $Scheduled = $.makeType<$Scheduled>(_.spec, "23c64270-532c-11ef-863f-6be9e
577577
const Scheduled: $.$expr_PathNode<$.TypeSet<$Scheduled, $.Cardinality.Many>, null> = _.syntax.$PathNode($.$toSet($Scheduled, $.Cardinality.Many), null);
578578

579579
export type $SimulatedFailureλShape = $.typeutil.flatten<$FailureλShape & {
580+
"validationErrors": $.PropertyDesc<$.ArrayType<_std.$str>, $.Cardinality.One, false, false, false, true>;
580581
}>;
581582
type $SimulatedFailure = $.ObjectType<"default::SimulatedFailure", $SimulatedFailureλShape, null, [
582583
...$Failure['__exclusives__'],
@@ -656,18 +657,18 @@ const Token: $.$expr_PathNode<$.TypeSet<$Token, $.Cardinality.Many>, null> = _.s
656657
export type $TransactionλShape = $.typeutil.flatten<Omit<$ProposalλShape, "<proposal"> & {
657658
"maxAmount": $.PropertyDesc<_std.$decimal, $.Cardinality.One, false, false, false, false>;
658659
"gasLimit": $.PropertyDesc<$uint256, $.Cardinality.One, false, false, false, true>;
659-
"executable": $.PropertyDesc<_std.$bool, $.Cardinality.One, false, false, false, true>;
660660
"unorderedOperations": $.LinkDesc<$Operation, $.Cardinality.AtLeastOne, {}, true, false, false, false>;
661661
"operations": $.LinkDesc<$Operation, $.Cardinality.AtLeastOne, {}, false, true, false, false>;
662662
"paymaster": $.PropertyDesc<$Address, $.Cardinality.One, false, false, false, false>;
663663
"feeToken": $.LinkDesc<$Token, $.Cardinality.One, {}, false, false, false, false>;
664664
"maxAmountFp": $.PropertyDesc<_std.$bigint, $.Cardinality.One, false, true, false, false>;
665665
"paymasterEthFees": $.LinkDesc<$PaymasterFees, $.Cardinality.One, {}, true, false, false, true>;
666666
"result": $.LinkDesc<$Result, $.Cardinality.AtMostOne, {}, true, false, false, false>;
667-
"status": $.PropertyDesc<$TransactionStatus, $.Cardinality.One, false, true, false, false>;
668667
"systx": $.LinkDesc<$SystemTx, $.Cardinality.AtMostOne, {}, true, false, false, false>;
669668
"results": $.LinkDesc<$Result, $.Cardinality.Many, {}, false, true, false, false>;
670669
"systxs": $.LinkDesc<$SystemTx, $.Cardinality.Many, {}, false, true, false, false>;
670+
"status": $.PropertyDesc<$TransactionStatus, $.Cardinality.One, false, true, false, false>;
671+
"executable": $.PropertyDesc<_std.$bool, $.Cardinality.One, false, true, false, false>;
671672
"<transaction[is ConfirmedSuccess]": $.LinkDesc<$ConfirmedSuccess, $.Cardinality.Many, {}, false, false, false, false>;
672673
"<transaction[is OptimisticSuccess]": $.LinkDesc<$OptimisticSuccess, $.Cardinality.Many, {}, false, false, false, false>;
673674
"<proposal[is PolicyState]": $.LinkDesc<$PolicyState, $.Cardinality.Many, {}, false, false, false, false>;

api/dbschema/interfaces.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,9 @@ export namespace $default {
241241
"cancelled": boolean;
242242
"scheduledFor": Date;
243243
}
244-
export interface SimulatedFailure extends Failure {}
244+
export interface SimulatedFailure extends Failure {
245+
"validationErrors": string[];
246+
}
245247
export interface SimulatedSuccess extends Success {}
246248
export interface SystemTx extends std.$Object {
247249
"proposal": Transaction;
@@ -269,18 +271,18 @@ export namespace $default {
269271
export interface Transaction extends Proposal {
270272
"maxAmount": string;
271273
"gasLimit": bigint;
272-
"executable": boolean;
273274
"unorderedOperations": Operation[];
274275
"operations": Operation[];
275276
"paymaster": string;
276277
"feeToken": Token;
277278
"maxAmountFp": bigint;
278279
"paymasterEthFees": PaymasterFees;
279280
"result"?: Result | null;
280-
"status": TransactionStatus;
281281
"systx"?: SystemTx | null;
282282
"results": Result[];
283283
"systxs": SystemTx[];
284+
"status": TransactionStatus;
285+
"executable": boolean;
284286
}
285287
export type TransactionStatus = "Pending" | "Scheduled" | "Executing" | "Successful" | "Failed" | "Cancelled";
286288
export interface Transferlike extends Event {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
CREATE MIGRATION m15nf2s2pczdhpncvwih5festgbvzushr5qfunppqaqahdonqo3nba
2+
ONTO m1b4kmwwkkxbx7nv3ze7u3c5td4y35hzgyinz422ny3npt4jpkcc3a
3+
{
4+
ALTER TYPE default::SimulatedFailure {
5+
CREATE REQUIRED PROPERTY validationErrors: array<std::str> {
6+
SET default := (<array<std::str>>[]);
7+
};
8+
};
9+
ALTER TYPE default::Transaction {
10+
ALTER PROPERTY executable {
11+
RESET default;
12+
USING (((.result IS default::SimulatedSuccess) ?? false));
13+
};
14+
ALTER PROPERTY status {
15+
USING (WITH
16+
result :=
17+
.result
18+
SELECT
19+
std::assert_exists((default::TransactionStatus.Pending IF ((NOT (EXISTS (result)) OR (result IS default::SimulatedSuccess)) OR (result IS default::SimulatedFailure)) ELSE (default::TransactionStatus.Executing IF (result IS default::OptimisticSuccess) ELSE (default::TransactionStatus.Successful IF (result IS default::ConfirmedSuccess) ELSE (default::TransactionStatus.Failed IF (result IS default::ConfirmedFailure) ELSE (default::TransactionStatus.Scheduled IF NOT (result[IS default::Scheduled].cancelled) ELSE default::TransactionStatus.Cancelled))))))
20+
);
21+
};
22+
};
23+
};

api/dbschema/transaction.esdl

+11-8
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,22 @@ module default {
2929
on source delete delete target;
3030
default := (insert PaymasterFees {});
3131
}
32-
required executable: bool { default := false; }
3332
multi link systxs := .<proposal[is SystemTx];
3433
link systx: SystemTx { constraint exclusive; } # Latest .timestamp
3534
multi link results := .<transaction[is Result];
3635
link result: Result { constraint exclusive; } # Latest .timestamp
3736
required property status := (
37+
with result := .result
3838
select assert_exists((
39-
TransactionStatus.Pending if (not .executable) else
40-
TransactionStatus.Executing if (not exists .result) else
41-
TransactionStatus.Successful if (.result is ConfirmedSuccess) else
42-
TransactionStatus.Failed if (.result is ConfirmedFailure) else
43-
TransactionStatus.Scheduled if (not .result[is Scheduled].cancelled) else
44-
TransactionStatus.Cancelled
39+
TransactionStatus.Pending if (not exists result or result is SimulatedSuccess or result is SimulatedFailure) else
40+
TransactionStatus.Executing if (result is OptimisticSuccess) else
41+
TransactionStatus.Successful if (result is ConfirmedSuccess) else
42+
TransactionStatus.Failed if (result is ConfirmedFailure) else
43+
TransactionStatus.Scheduled if (not result[is Scheduled].cancelled) else
44+
TransactionStatus.Cancelled # result is Scheduled
4545
))
4646
);
47+
required executable := (.result is SimulatedSuccess) ?? false;
4748
}
4849

4950
type SystemTx {
@@ -93,7 +94,9 @@ module default {
9394

9495
type SimulatedSuccess extending Success {}
9596

96-
type SimulatedFailure extending Failure {}
97+
type SimulatedFailure extending Failure {
98+
required validationErrors: array<str> { default := <array<str>>[]; };
99+
}
97100

98101
type OptimisticSuccess extending Success {}
99102

api/src/feat/simulations/insert-simulated-failure.edgeql

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ insert SimulatedFailure {
22
transaction := <Transaction><uuid>$transaction,
33
response := <Bytes>$response,
44
gasUsed := <bigint>$gasUsed,
5-
reason := <str>$reason
5+
reason := <str>$reason,
6+
validationErrors := <array<str>>$validationErrors
67
}

api/src/feat/simulations/insert-simulated-failure.query.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export type InsertSimulatedFailureArgs = {
77
readonly "response": string;
88
readonly "gasUsed": bigint;
99
readonly "reason": string;
10+
readonly "validationErrors": ReadonlyArray<string>;
1011
};
1112

1213
export type InsertSimulatedFailureReturns = {
@@ -19,7 +20,8 @@ insert SimulatedFailure {
1920
transaction := <Transaction><uuid>$transaction,
2021
response := <Bytes>$response,
2122
gasUsed := <bigint>$gasUsed,
22-
reason := <str>$reason
23+
reason := <str>$reason,
24+
validationErrors := <array<str>>$validationErrors
2325
}`, args);
2426

2527
}

api/src/feat/simulations/simulations.worker.ts

+22-12
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@ import {
1212
asUUID,
1313
decodeTransfer,
1414
encodeOperations,
15+
tryOrIgnore,
1516
} from 'lib';
1617
import { DatabaseService } from '~/core/database';
1718
import e, { $infer } from '~/edgeql-js';
1819
import { and } from '~/core/database';
1920
import { RUNNING_JOB_STATUSES, TypedJob, createQueue } from '~/core/bull/bull.util';
2021
import { Worker } from '~/core/bull/Worker';
21-
import { ERC20, SYNCSWAP } from 'lib/dapps';
22+
import { ERC20 } from 'lib/dapps';
2223
import { NetworksService } from '~/core/networks';
2324
import { TX_SHAPE, transactionAsTx } from '~/feat/transactions/transactions.util';
2425
import { Shape } from '~/core/database';
@@ -80,7 +81,7 @@ export class SimulationsWorker extends Worker<SimulationsQueue> {
8081
);
8182
if (!t) return 'Transaction not found';
8283

83-
const validPromise = this.isValidatable(t);
84+
const validationErrorsPromise = this.getValidationErrors(t);
8485
const account = asUAddress(t.account.address);
8586
const localAccount = asAddress(account);
8687
const chain = asChain(account);
@@ -100,7 +101,10 @@ export class SimulationsWorker extends Worker<SimulationsQueue> {
100101
});
101102

102103
const error = trace.error || trace.revertReason;
103-
const result = await (!error
104+
const validationErrors = await validationErrorsPromise;
105+
const success = !error && !validationErrors.length;
106+
107+
const result = await (success
104108
? this.db.exec(insertSimulatedSuccess, {
105109
transaction: t.id,
106110
response: trace.output,
@@ -110,16 +114,16 @@ export class SimulationsWorker extends Worker<SimulationsQueue> {
110114
transaction: t.id,
111115
response: trace.output,
112116
gasUsed: trace.gasUsed,
113-
reason: error,
117+
reason: error ?? '',
118+
validationErrors,
114119
}));
115120

116121
const logs = await this.simulateEvents(t);
117122
await this.events.processSimulatedAndOptimistic({ chain, logs, result: asUUID(result.id) });
118123

119124
this.proposals.event({ id: asUUID(t.id), account }, ProposalEvent.simulated);
120125

121-
const valid = await validPromise;
122-
return { executable: valid && !error };
126+
return { executable: success };
123127
}
124128

125129
private async simulateEvents(t: TransactionExecutableShape) {
@@ -153,7 +157,7 @@ export class SimulationsWorker extends Worker<SimulationsQueue> {
153157
const selector = data && size(data) >= 4 && slice(data, 0, 4);
154158
if (!selector) continue;
155159

156-
const f = decodeFunctionData({ abi: EVENTS_ABI, data });
160+
const f = tryOrIgnore(() => decodeFunctionData({ abi: EVENTS_ABI, data }));
157161
match(f)
158162
.with({ functionName: 'transfer' }, (f) => {
159163
logs.push({
@@ -242,6 +246,7 @@ export class SimulationsWorker extends Worker<SimulationsQueue> {
242246
// }),
243247
// });
244248
// })
249+
.with(undefined, () => {})
245250
.exhaustive();
246251

247252
// TODO: swap
@@ -250,12 +255,14 @@ export class SimulationsWorker extends Worker<SimulationsQueue> {
250255
return logs;
251256
}
252257

253-
private async isValidatable(t: TransactionExecutableShape) {
254-
if (!t.policy.isActive) return false;
255-
if (t.validationErrors.length) return false;
258+
private async getValidationErrors(t: TransactionExecutableShape) {
259+
const errors: string[] = [];
260+
261+
if (!t.policy.isActive) errors.push('Policy not active');
262+
if (t.validationErrors.length) errors.push('Policy validation errors');
256263

257264
const approved = t.policy.threshold <= t.approvals.length;
258-
if (!approved) return false;
265+
if (!approved) errors.push('Insufficient approval');
259266

260267
// Check all limits
261268
const transfers = transactionAsTx(t)
@@ -280,7 +287,10 @@ export class SimulationsWorker extends Worker<SimulationsQueue> {
280287
}),
281288
);
282289

283-
return limitResults.every((r) => r);
290+
const sufficientSpending = limitResults.every((r) => r);
291+
if (!sufficientSpending) errors.push('Greater than allowed spending');
292+
293+
return errors;
284294
}
285295

286296
async bootstrap() {

0 commit comments

Comments
 (0)