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

Commit d0a7afe

Browse files
authored
Merge pull request #287 from zallo-labs/Z-341-responsive-transaction
Z 341 responsive transaction
2 parents 430c98c + 98d7965 commit d0a7afe

File tree

95 files changed

+2093
-1637
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+2093
-1637
lines changed
Binary file not shown.

api/dbschema/edgeql-js/__spec__.ts

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

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

+1-2
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,10 @@ const NonEmptyStr: $.scalarTypeWithConstructor<_std.$str, never> = $.makeType<$.
4747
export type $TransactionStatus = {
4848
"Pending": $.$expr_Literal<$TransactionStatus>;
4949
"Scheduled": $.$expr_Literal<$TransactionStatus>;
50-
"Executing": $.$expr_Literal<$TransactionStatus>;
5150
"Successful": $.$expr_Literal<$TransactionStatus>;
5251
"Failed": $.$expr_Literal<$TransactionStatus>;
5352
"Cancelled": $.$expr_Literal<$TransactionStatus>;
54-
} & $.EnumType<"default::TransactionStatus", ["Pending", "Scheduled", "Executing", "Successful", "Failed", "Cancelled"]>;
53+
} & $.EnumType<"default::TransactionStatus", ["Pending", "Scheduled", "Successful", "Failed", "Cancelled"]>;
5554
const TransactionStatus: $TransactionStatus = $.makeType<$TransactionStatus>(_.spec, "d2eb5a82-5489-11ef-a64b-c5eeac9d34b6", _.syntax.literal);
5655

5756
export type $UAddress = $.ScalarType<"std::str", string>;

api/dbschema/events.esdl

+1-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ module default {
1010
default := true;
1111
rewrite insert, update using (exists __subject__.result);
1212
};
13-
required confirmed: bool {
14-
# rewrite insert, update using ((__subject__.result is Confirmed) ?? true);
15-
}
13+
required confirmed: bool; # rewrite insert, update using ((__subject__.result is Confirmed) ?? true);
1614

1715
access policy members_can_select
1816
allow select

api/dbschema/interfaces.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ export namespace $default {
284284
"executable": boolean;
285285
"status": TransactionStatus;
286286
}
287-
export type TransactionStatus = "Pending" | "Scheduled" | "Executing" | "Successful" | "Failed" | "Cancelled";
287+
export type TransactionStatus = "Pending" | "Scheduled" | "Successful" | "Failed" | "Cancelled";
288288
export interface Transferlike extends Event {
289289
"tokenAddress": string;
290290
"token"?: Token | null;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
CREATE MIGRATION m174x3tft7rqwxzekegp7qad4qlscof7tojfcmw4wielhp7h4mqsya
2+
ONTO m17qamgbzvrq5axhdxhdn526i3wz42l5yt3fjdgog73ihlovmrb2sq
3+
{
4+
ALTER TYPE default::Result {
5+
ALTER TRIGGER update_tx_result WHEN (((__new__.timestamp >= __new__.transaction.result.timestamp) ?? true));
6+
};
7+
ALTER TYPE default::Transaction {
8+
ALTER PROPERTY status {
9+
USING (WITH
10+
result :=
11+
.result
12+
SELECT
13+
std::assert_exists((default::TransactionStatus.Pending IF (((result IS default::SimulatedSuccess) OR (result IS default::SimulatedFailure)) ?? true) ELSE (default::TransactionStatus.Successful IF (((result IS default::OptimisticSuccess) OR (result IS default::ConfirmedSuccess)) ?? false) ELSE (default::TransactionStatus.Failed IF (result IS default::ConfirmedFailure) ELSE (default::TransactionStatus.Scheduled IF NOT (result[IS default::Scheduled].cancelled) ELSE default::TransactionStatus.Cancelled)))))
14+
);
15+
};
16+
};
17+
ALTER SCALAR TYPE default::TransactionStatus EXTENDING enum<Pending, Scheduled, Successful, Failed, Cancelled>;
18+
};

api/dbschema/transaction.esdl

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module default {
1111
required activation: decimal { constraint min_value(0); default := 0; }
1212
}
1313

14-
scalar type TransactionStatus extending enum<'Pending', 'Scheduled', 'Executing', 'Successful', 'Failed', 'Cancelled'>;
14+
scalar type TransactionStatus extending enum<'Pending', 'Scheduled', 'Successful', 'Failed', 'Cancelled'>;
1515

1616
type Transaction extending Proposal {
1717
required multi unorderedOperations: Operation {
@@ -37,8 +37,7 @@ module default {
3737
with result := .result
3838
select assert_exists((
3939
TransactionStatus.Pending if ((result is SimulatedSuccess or result is SimulatedFailure) ?? true) else
40-
TransactionStatus.Executing if (result is OptimisticSuccess) else
41-
TransactionStatus.Successful if (result is ConfirmedSuccess) else
40+
TransactionStatus.Successful if ((result is OptimisticSuccess or result is ConfirmedSuccess) ?? false) else
4241
TransactionStatus.Failed if (result is ConfirmedFailure) else
4342
TransactionStatus.Scheduled if (not result[is Scheduled].cancelled) else
4443
TransactionStatus.Cancelled # result is Scheduled
@@ -81,7 +80,8 @@ module default {
8180
multi link events := .<result[is Event];
8281
multi link transfers := .events[is Transfer];
8382

84-
trigger update_tx_result after insert for each do (
83+
trigger update_tx_result after insert for each
84+
when ((__new__.timestamp >= __new__.transaction.result.timestamp) ?? true) do (
8585
update __new__.transaction set { result := __new__ }
8686
);
8787
}

api/schema.graphql

+22-13
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ interface Confirmed implements Node & Result {
173173
id: ID!
174174
networkEthFee: Decimal!
175175
response: Bytes!
176-
systemTx: SystemTx
176+
systx: SystemTx
177177
timestamp: DateTime!
178178
transaction: Transaction!
179179
transfers: [Transfer!]!
@@ -188,7 +188,7 @@ type ConfirmedFailure implements Confirmed & Failure & Node & Result {
188188
networkEthFee: Decimal!
189189
reason: String
190190
response: Bytes!
191-
systemTx: SystemTx
191+
systx: SystemTx
192192
timestamp: DateTime!
193193
transaction: Transaction!
194194
transfers: [Transfer!]!
@@ -202,7 +202,7 @@ type ConfirmedSuccess implements Confirmed & Node & Result & Success {
202202
id: ID!
203203
networkEthFee: Decimal!
204204
response: Bytes!
205-
systemTx: SystemTx
205+
systx: SystemTx
206206
timestamp: DateTime!
207207
transaction: Transaction!
208208
transfers: [Transfer!]!
@@ -282,10 +282,20 @@ input EstimateFeesPerGasInput {
282282
feeToken: UAddress!
283283
}
284284

285+
type EstimatedFeeParts {
286+
maxFeePerGas: Decimal!
287+
maxPriorityFeePerGas: Decimal!
288+
networkFee: Decimal!
289+
paymasterFees: PaymasterFees!
290+
total: Decimal!
291+
}
292+
285293
type EstimatedTransactionFees implements CustomNode {
294+
eth: EstimatedFeeParts!
295+
feeToken: EstimatedFeeParts!
296+
gasLimit: Uint256!
297+
gasPerPubdataLimit: Uint256!
286298
id: ID!
287-
maxNetworkEthFee: Decimal!
288-
paymasterEthFees: PaymasterFees!
289299
}
290300

291301
interface Event implements Node {
@@ -311,7 +321,7 @@ interface Failure implements Node & Result {
311321
id: ID!
312322
reason: String
313323
response: Bytes!
314-
systemTx: SystemTx
324+
systx: SystemTx
315325
timestamp: DateTime!
316326
transaction: Transaction!
317327
transfers: [Transfer!]!
@@ -423,7 +433,7 @@ type OptimisticSuccess implements Node & Result & Success {
423433
gasUsed: BigInt!
424434
id: ID!
425435
response: Bytes!
426-
systemTx: SystemTx
436+
systx: SystemTx
427437
timestamp: DateTime!
428438
transaction: Transaction!
429439
transfers: [Transfer!]!
@@ -705,7 +715,7 @@ interface Result implements Node {
705715
gasUsed: BigInt!
706716
id: ID!
707717
response: Bytes!
708-
systemTx: SystemTx
718+
systx: SystemTx
709719
timestamp: DateTime!
710720
transaction: Transaction!
711721
transfers: [Transfer!]!
@@ -718,7 +728,7 @@ type Scheduled implements Node & Result {
718728
id: ID!
719729
response: Bytes!
720730
scheduledFor: DateTime!
721-
systemTx: SystemTx
731+
systx: SystemTx
722732
timestamp: DateTime!
723733
transaction: Transaction!
724734
transfers: [Transfer!]!
@@ -733,7 +743,7 @@ type SimulatedFailure implements Failure & Node & Result {
733743
id: ID!
734744
reason: String
735745
response: Bytes!
736-
systemTx: SystemTx
746+
systx: SystemTx
737747
timestamp: DateTime!
738748
transaction: Transaction!
739749
transfers: [Transfer!]!
@@ -746,7 +756,7 @@ type SimulatedSuccess implements Node & Result & Success {
746756
id: ID!
747757
reason: String
748758
response: Bytes!
749-
systemTx: SystemTx
759+
systx: SystemTx
750760
timestamp: DateTime!
751761
transaction: Transaction!
752762
transfers: [Transfer!]!
@@ -771,7 +781,7 @@ interface Success implements Node & Result {
771781
gasUsed: BigInt!
772782
id: ID!
773783
response: Bytes!
774-
systemTx: SystemTx
784+
systx: SystemTx
775785
timestamp: DateTime!
776786
transaction: Transaction!
777787
transfers: [Transfer!]!
@@ -901,7 +911,6 @@ type TransactionPreparation implements CustomNode {
901911

902912
enum TransactionStatus {
903913
Cancelled
904-
Executing
905914
Failed
906915
Pending
907916
Scheduled
+1-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
import { Global, Module } from '@nestjs/common';
22
import { NetworksHealthIndicator } from './networks.health';
33
import { NetworksService } from './networks.service';
4-
import { registerBullQueue } from '../bull/bull.util';
5-
import { NetworkQueue, NetworkWorker } from './networks.worker';
64

75
@Global()
86
@Module({
9-
imports: [...registerBullQueue(NetworkQueue)],
107
exports: [NetworksService, NetworksHealthIndicator],
11-
providers: [NetworksService, NetworksHealthIndicator, NetworkWorker],
8+
providers: [NetworksService, NetworksHealthIndicator],
129
})
1310
export class NetworksModule {}

api/src/core/networks/networks.service.ts

+39-33
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { runExclusively } from '~/util/mutex';
3030
import { ETH } from 'lib/dapps';
3131
import { fromPromise } from 'neverthrow';
3232
import { PartialK } from '~/util/types';
33+
import Decimal from 'decimal.js';
3334

3435
export type Network = ReturnType<typeof create>;
3536

@@ -90,7 +91,8 @@ function create({ chainKey, redis }: CreateParams) {
9091
...eip712WalletActions()(client),
9192
...walletActions(client, transport, redis),
9293
...blockDetails(client),
93-
...estimatedFeesPerGas(client, redis),
94+
feeParams: feeParams(client, redis),
95+
maxFeePerGas: maxFeePerGas(client, redis),
9496
sendAccountTransaction: sendAccountTransaction(client, redis),
9597
traceCall: traceCall(client),
9698
}));
@@ -163,41 +165,48 @@ function blockDetails(client: Client) {
163165
};
164166
}
165167

166-
export function estimatedFeesPerGasKey(chain: Chain) {
167-
return `estimatedFeesPerGasKey:${chain}`;
168+
export interface NetworkFeeParams {
169+
maxFeePerGas: Decimal;
170+
maxPriorityFeePerGas: Decimal;
171+
gasPerPubdataLimit: bigint;
168172
}
169173

170-
async function getEstimatedFeesPerGas(client: Client, redis: Redis): Promise<FeeValuesEIP1559> {
171-
const cached = await redis.get(estimatedFeesPerGasKey(client.chain.key));
172-
if (cached) {
173-
const p = JSON.parse(cached) as any;
174-
return {
175-
maxFeePerGas: BigInt(p.maxFeePerGas),
176-
maxPriorityFeePerGas: BigInt(p.maxPriorityFeePerGas),
177-
} satisfies FeeValuesEIP1559;
178-
}
179-
180-
const r = await client.estimateFeesPerGas();
181-
if (r.maxFeePerGas === undefined || r.maxPriorityFeePerGas === undefined)
182-
throw new Error('Gas price estimates non EIP-1559');
183-
184-
return r;
185-
}
186-
187-
function estimatedFeesPerGas(client: Client, redis: Redis) {
188-
const estimatedFeesPerGas = async () => {
189-
const v = await getEstimatedFeesPerGas(client, redis);
174+
function feeParams(client: Client, redis: Redis) {
175+
const { estimateFee } = publicActionsL2()(client);
176+
177+
return async (): Promise<NetworkFeeParams> => {
178+
const r = await (async () => {
179+
const key = `feeParams:${client.chain.key}`;
180+
const cached = await redis.get(key);
181+
if (cached) {
182+
const p = JSON.parse(cached) as any;
183+
return {
184+
maxFeePerGas: BigInt(p.maxFeePerGas),
185+
maxPriorityFeePerGas: BigInt(p.maxPriorityFeePerGas),
186+
gasPerPubdataLimit: p.gasPerPubdataLimit,
187+
};
188+
}
189+
190+
const fresh = await estimateFee({
191+
/* estimateFee required to get gasPerPubdataLimit */
192+
account: '0x1111111111111111111111111111111111111111',
193+
to: '0x1111111111111111111111111111111111111111',
194+
});
195+
redis.set(key, JSON.stringify(fresh), 'EX', 5);
196+
return fresh;
197+
})();
190198

191199
return {
192-
maxFeePerGas: asDecimal(v.maxFeePerGas!, ETH),
193-
maxPriorityFeePerGas: asDecimal(v.maxPriorityFeePerGas!, ETH),
200+
maxFeePerGas: asDecimal(r.maxFeePerGas, ETH),
201+
maxPriorityFeePerGas: asDecimal(r.maxPriorityFeePerGas, ETH),
202+
gasPerPubdataLimit: r.gasPerPubdataLimit,
194203
};
195204
};
205+
}
196206

197-
return {
198-
estimatedFeesPerGas,
199-
estimatedMaxFeePerGas: async () => (await estimatedFeesPerGas()).maxFeePerGas,
200-
};
207+
function maxFeePerGas(client: Client, redis: Redis) {
208+
const getFeeParams = feeParams(client, redis);
209+
return async () => (await getFeeParams()).maxFeePerGas;
201210
}
202211

203212
export type TransactionWithDetailedOutput = {
@@ -229,14 +238,10 @@ export type SendAccountTransactionReturn = ReturnType<ReturnType<typeof sendAcco
229238
function sendAccountTransaction(client: Client, redis: Redis) {
230239
// Transactions must be submitted sequentially due to requirement for incrementing nonces
231240
return async (tx: SendAccountTransactionParams) => {
232-
const feesPerGas = await getEstimatedFeesPerGas(client, redis);
233-
234241
return await runExclusively(
235242
async () => {
236243
const serialized = client.chain.serializers.transaction({
237244
chainId: client.chain.id,
238-
maxFeePerGas: feesPerGas.maxFeePerGas!,
239-
maxPriorityFeePerGas: feesPerGas.maxPriorityFeePerGas!,
240245
nonce: await client.getTransactionCount({ address: tx.from }),
241246
...tx,
242247
});
@@ -302,6 +307,7 @@ export interface TraceCallParams {
302307
block?: TraceCallSchema['Parameters'][1];
303308
options?: TraceCallSchema['Parameters'][2];
304309
}
310+
export type TraceCallReturnType = Awaited<ReturnType<ReturnType<typeof traceCall>>>;
305311

306312
function traceCall(client: Client) {
307313
return async (params: TraceCallParams) => {

api/src/core/networks/networks.worker.ts

-45
This file was deleted.

0 commit comments

Comments
 (0)