@develit-services/blockchain 0.8.2 → 0.8.4
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/dist/database/schema.cjs +5 -1
- package/dist/database/schema.d.cts +1 -1
- package/dist/database/schema.d.mts +1 -1
- package/dist/database/schema.d.ts +1 -1
- package/dist/database/schema.mjs +3 -1
- package/dist/export/worker.cjs +20 -625
- package/dist/export/worker.d.cts +2 -2
- package/dist/export/worker.d.mts +2 -2
- package/dist/export/worker.d.ts +2 -2
- package/dist/export/worker.mjs +20 -625
- package/dist/export/workflows.cjs +100 -85
- package/dist/export/workflows.mjs +96 -81
- package/dist/shared/blockchain.BKGlFbOW.mjs +68 -0
- package/dist/shared/{blockchain.CtIjPvX8.d.cts → blockchain.Br6esGv4.d.cts} +3 -3
- package/dist/shared/{blockchain.DTJULMBV.mjs → blockchain.CKh8Fs7w.mjs} +12 -1
- package/dist/shared/{blockchain.BBjLLe8v.cjs → blockchain.Cjq9eH7Z.cjs} +13 -0
- package/dist/shared/blockchain.DUhjXgba.d.cts +1107 -0
- package/dist/shared/blockchain.DUhjXgba.d.mts +1107 -0
- package/dist/shared/blockchain.DUhjXgba.d.ts +1107 -0
- package/dist/shared/{blockchain.DZbyq0JM.d.mts → blockchain.DcWSUM60.d.mts} +3 -3
- package/dist/shared/{blockchain.5Ld6uEay.d.ts → blockchain.DurPotrN.d.ts} +3 -3
- package/dist/shared/blockchain.JBv4ipVR.cjs +335 -0
- package/dist/shared/blockchain.ZJPECySM.cjs +74 -0
- package/dist/shared/blockchain.wsLSmIaf.mjs +332 -0
- package/dist/types.cjs +3 -1
- package/dist/types.d.cts +12 -4
- package/dist/types.d.mts +12 -4
- package/dist/types.d.ts +12 -4
- package/dist/types.mjs +1 -1
- package/package.json +2 -2
- package/dist/shared/blockchain.0tUJ62WT.mjs +0 -6
- package/dist/shared/blockchain.BBvwu2_7.cjs +0 -39
- package/dist/shared/blockchain.Cx60lJ0c.d.cts +0 -566
- package/dist/shared/blockchain.Cx60lJ0c.d.mts +0 -566
- package/dist/shared/blockchain.Cx60lJ0c.d.ts +0 -566
- package/dist/shared/blockchain.DN735AwB.cjs +0 -8
- package/dist/shared/blockchain._wwKu1qP.mjs +0 -35
|
@@ -1,38 +1,57 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const backendSdk = require('@develit-io/backend-sdk');
|
|
4
|
-
const
|
|
4
|
+
const blockchain = require('../shared/blockchain.JBv4ipVR.cjs');
|
|
5
5
|
const drizzleOrm = require('drizzle-orm');
|
|
6
6
|
const cloudflare_workers = require('cloudflare:workers');
|
|
7
7
|
const cloudflare_workflows = require('cloudflare:workflows');
|
|
8
8
|
const d1 = require('drizzle-orm/d1');
|
|
9
|
-
|
|
10
|
-
const chains = require('viem/chains');
|
|
11
|
-
require('../shared/blockchain.BBvwu2_7.cjs');
|
|
9
|
+
require('../shared/blockchain.ZJPECySM.cjs');
|
|
12
10
|
require('drizzle-orm/sqlite-core');
|
|
11
|
+
require('../shared/blockchain.Cjq9eH7Z.cjs');
|
|
12
|
+
require('zod');
|
|
13
|
+
require('viem');
|
|
14
|
+
require('viem/accounts');
|
|
15
|
+
|
|
16
|
+
const updateAddressLastSyncBlockCommand = (db, {
|
|
17
|
+
lastSyncBlock,
|
|
18
|
+
addressId
|
|
19
|
+
}) => {
|
|
20
|
+
const command = db.update(blockchain.tables.address).set({
|
|
21
|
+
lastSyncBlock
|
|
22
|
+
}).where(drizzleOrm.eq(blockchain.tables.address.id, addressId)).returning();
|
|
23
|
+
return {
|
|
24
|
+
command
|
|
25
|
+
};
|
|
26
|
+
};
|
|
13
27
|
|
|
14
28
|
const updateAddressLastSyncCommand = (db, {
|
|
15
29
|
lastSyncAt,
|
|
16
30
|
addressId,
|
|
17
31
|
lastSyncMetadata
|
|
18
32
|
}) => {
|
|
19
|
-
const command = db.update(
|
|
33
|
+
const command = db.update(blockchain.tables.address).set({
|
|
20
34
|
lastSyncAt,
|
|
21
35
|
lastSyncMetadata
|
|
22
|
-
}).where(drizzleOrm.eq(
|
|
36
|
+
}).where(drizzleOrm.eq(blockchain.tables.address.id, addressId)).returning();
|
|
23
37
|
return {
|
|
24
38
|
command
|
|
25
39
|
};
|
|
26
40
|
};
|
|
27
41
|
|
|
28
42
|
const getAddressById = async (db, id) => {
|
|
29
|
-
const address = await db.select().from(
|
|
43
|
+
const address = await db.select().from(blockchain.tables.address).where(drizzleOrm.eq(blockchain.tables.address.id, id)).get();
|
|
30
44
|
return address;
|
|
31
45
|
};
|
|
32
46
|
|
|
47
|
+
const getContractAddresses = async (db, { connector }) => {
|
|
48
|
+
const addresses = await db.select().from(blockchain.tables.tokens).where(drizzleOrm.eq(blockchain.tables.tokens.connector, connector)).all();
|
|
49
|
+
return addresses;
|
|
50
|
+
};
|
|
51
|
+
|
|
33
52
|
const createTransactionCommand = (db, { transaction }) => {
|
|
34
53
|
const id = backendSdk.uuidv4();
|
|
35
|
-
const command = db.insert(
|
|
54
|
+
const command = db.insert(blockchain.tables.transaction).values({ ...transaction, id }).onConflictDoNothing().returning();
|
|
36
55
|
return { command };
|
|
37
56
|
};
|
|
38
57
|
|
|
@@ -48,7 +67,7 @@ function pushToQueue(queue, message) {
|
|
|
48
67
|
class BlockchainSyncAddressTransactions extends cloudflare_workers.WorkflowEntrypoint {
|
|
49
68
|
async run(event, step) {
|
|
50
69
|
const { addressId } = event.payload;
|
|
51
|
-
const db = d1.drizzle(this.env.BLOCKCHAIN_D1, { schema:
|
|
70
|
+
const db = d1.drizzle(this.env.BLOCKCHAIN_D1, { schema: blockchain.tables });
|
|
52
71
|
if (!addressId) {
|
|
53
72
|
throw new cloudflare_workflows.NonRetryableError(`Haven't obtained addressId to load.`);
|
|
54
73
|
}
|
|
@@ -61,98 +80,86 @@ class BlockchainSyncAddressTransactions extends cloudflare_workers.WorkflowEntry
|
|
|
61
80
|
`Blockchain address not found: ${addressId}.`
|
|
62
81
|
);
|
|
63
82
|
}
|
|
64
|
-
return
|
|
83
|
+
return {
|
|
84
|
+
...address2,
|
|
85
|
+
lastSyncBlock: address2.lastSyncBlock?.toString() ?? null
|
|
86
|
+
};
|
|
65
87
|
});
|
|
66
88
|
if (!address.lastSyncAt) {
|
|
67
|
-
throw new
|
|
89
|
+
throw new cloudflare_workflows.NonRetryableError(
|
|
90
|
+
`lastSyncedAt is not set for address: ${address}`
|
|
91
|
+
);
|
|
68
92
|
}
|
|
69
93
|
const transactions = await step.do(
|
|
70
|
-
|
|
94
|
+
`fetch address transactions`,
|
|
71
95
|
{
|
|
72
96
|
retries: { limit: 5, delay: 2e3, backoff: "constant" },
|
|
73
97
|
timeout: "30 seconds"
|
|
74
98
|
},
|
|
75
99
|
async () => {
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
})).data?.secretValue || "";
|
|
79
|
-
const client = viem.createPublicClient({
|
|
80
|
-
chain: chains.gnosisChiado,
|
|
81
|
-
transport: viem.http(rpcUrl)
|
|
100
|
+
const tokens = await getContractAddresses(db, {
|
|
101
|
+
connector: address.connector
|
|
82
102
|
});
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const blockTimestamp = Number(block.timestamp);
|
|
98
|
-
const lastSyncedTimestampNum = typeof lastSyncedTimestamp === "number" ? lastSyncedTimestamp : Number(lastSyncedTimestamp);
|
|
99
|
-
if (blockTimestamp <= lastSyncedTimestampNum) {
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
for (const tx of block.transactions) {
|
|
103
|
-
if (typeof tx === "string" || !tx.to) continue;
|
|
104
|
-
if (tx.from.toLowerCase() === address.number.toLowerCase()) {
|
|
105
|
-
const receipt = await client.getTransactionReceipt({
|
|
106
|
-
hash: tx.hash
|
|
107
|
-
});
|
|
108
|
-
allTransactions.push({
|
|
109
|
-
hash: tx.hash,
|
|
110
|
-
from: tx.from,
|
|
111
|
-
to: tx.to,
|
|
112
|
-
value: tx.value.toString(),
|
|
113
|
-
blockNumber: block.number.toString(),
|
|
114
|
-
blockHash: block.hash,
|
|
115
|
-
gasUsed: receipt.gasUsed.toString(),
|
|
116
|
-
gasPrice: tx.gasPrice?.toString() ?? "",
|
|
117
|
-
timestamp: blockTimestamp,
|
|
118
|
-
status: receipt.status
|
|
119
|
-
});
|
|
103
|
+
if (!tokens || tokens.length === 0) {
|
|
104
|
+
throw new cloudflare_workflows.NonRetryableError(
|
|
105
|
+
`No contract addresses found for connector: ${address.connector}`
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
const connector = await blockchain.initiateConnector({
|
|
109
|
+
chain: address.connector,
|
|
110
|
+
env: this.env,
|
|
111
|
+
tokens,
|
|
112
|
+
connectedAddresses: [
|
|
113
|
+
{
|
|
114
|
+
id: address.id,
|
|
115
|
+
number: address.number,
|
|
116
|
+
connector: address.connector
|
|
120
117
|
}
|
|
118
|
+
]
|
|
119
|
+
});
|
|
120
|
+
const result = await connector.getAllAddressTransactions({
|
|
121
|
+
address: address.number,
|
|
122
|
+
filter: {
|
|
123
|
+
fromBlock: address.lastSyncBlock ? BigInt(address.lastSyncBlock) : null
|
|
121
124
|
}
|
|
122
|
-
}
|
|
123
|
-
return
|
|
125
|
+
});
|
|
126
|
+
return {
|
|
127
|
+
transactions: result.transactions,
|
|
128
|
+
latestBlock: result.latestBlock.toString()
|
|
129
|
+
};
|
|
124
130
|
}
|
|
125
131
|
);
|
|
126
|
-
if (transactions.length > 0) {
|
|
132
|
+
if (transactions.transactions.length > 0) {
|
|
127
133
|
await step.do(
|
|
128
|
-
|
|
134
|
+
`process new transactions and update lastSyncAt`,
|
|
129
135
|
async () => {
|
|
130
|
-
const createCommands = transactions.map(
|
|
136
|
+
const createCommands = transactions.transactions.map(
|
|
131
137
|
(tx) => createTransactionCommand(db, { transaction: tx }).command
|
|
132
138
|
);
|
|
133
|
-
const eventsToEmit = transactions.map(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
139
|
+
const eventsToEmit = transactions.transactions.map((tx) => ({
|
|
140
|
+
eventType: "BLOCKCHAIN_TRANSACTION",
|
|
141
|
+
blockchainTransaction: {
|
|
142
|
+
address: address.number,
|
|
143
|
+
hash: tx.hash,
|
|
144
|
+
from: tx.from,
|
|
145
|
+
to: tx.to,
|
|
146
|
+
value: tx.value,
|
|
147
|
+
blockNumber: tx.blockNumber,
|
|
148
|
+
blockHash: tx.blockHash,
|
|
149
|
+
gasUsed: tx.gasUsed,
|
|
150
|
+
gasPrice: tx.gasPrice,
|
|
151
|
+
timestamp: tx.timestamp,
|
|
152
|
+
status: tx.status,
|
|
153
|
+
decimals: tx.decimals,
|
|
154
|
+
connector: address.connector,
|
|
155
|
+
ticker: tx.ticker
|
|
156
|
+
},
|
|
157
|
+
metadata: {
|
|
158
|
+
correlationId: backendSdk.uuidv4(),
|
|
159
|
+
entityId: backendSdk.uuidv4(),
|
|
160
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
161
|
+
}
|
|
162
|
+
}));
|
|
156
163
|
const lastSyncMetadata = {
|
|
157
164
|
eventsEmitted: eventsToEmit.length
|
|
158
165
|
};
|
|
@@ -161,9 +168,17 @@ class BlockchainSyncAddressTransactions extends cloudflare_workers.WorkflowEntry
|
|
|
161
168
|
lastSyncAt: now,
|
|
162
169
|
lastSyncMetadata
|
|
163
170
|
}).command;
|
|
171
|
+
const updateLastSyncBlockCommand = updateAddressLastSyncBlockCommand(db, {
|
|
172
|
+
addressId: address.id,
|
|
173
|
+
lastSyncBlock: BigInt(transactions.latestBlock)
|
|
174
|
+
}).command;
|
|
164
175
|
if (eventsToEmit.length) {
|
|
165
176
|
await db.batch(
|
|
166
|
-
backendSdk.asNonEmpty([
|
|
177
|
+
backendSdk.asNonEmpty([
|
|
178
|
+
updateLastSyncCommand,
|
|
179
|
+
updateLastSyncBlockCommand,
|
|
180
|
+
...createCommands
|
|
181
|
+
])
|
|
167
182
|
);
|
|
168
183
|
await pushToQueue(
|
|
169
184
|
this.env.QUEUE_BUS_QUEUE,
|
|
@@ -178,7 +193,7 @@ class BlockchainSyncAddressTransactions extends cloudflare_workers.WorkflowEntry
|
|
|
178
193
|
);
|
|
179
194
|
}
|
|
180
195
|
await step.sleep(
|
|
181
|
-
|
|
196
|
+
`sleep until next sync`,
|
|
182
197
|
`${address.syncIntervalS} seconds`
|
|
183
198
|
);
|
|
184
199
|
}
|
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
import { uuidv4, asNonEmpty } from '@develit-io/backend-sdk';
|
|
2
|
-
import { t as tables } from '../shared/blockchain.
|
|
2
|
+
import { t as tables, i as initiateConnector } from '../shared/blockchain.wsLSmIaf.mjs';
|
|
3
3
|
import { eq } from 'drizzle-orm';
|
|
4
4
|
import { WorkflowEntrypoint } from 'cloudflare:workers';
|
|
5
5
|
import { NonRetryableError } from 'cloudflare:workflows';
|
|
6
6
|
import { drizzle } from 'drizzle-orm/d1';
|
|
7
|
-
import
|
|
8
|
-
import { gnosisChiado } from 'viem/chains';
|
|
9
|
-
import '../shared/blockchain._wwKu1qP.mjs';
|
|
7
|
+
import '../shared/blockchain.BKGlFbOW.mjs';
|
|
10
8
|
import 'drizzle-orm/sqlite-core';
|
|
9
|
+
import '../shared/blockchain.CKh8Fs7w.mjs';
|
|
10
|
+
import 'zod';
|
|
11
|
+
import 'viem';
|
|
12
|
+
import 'viem/accounts';
|
|
13
|
+
|
|
14
|
+
const updateAddressLastSyncBlockCommand = (db, {
|
|
15
|
+
lastSyncBlock,
|
|
16
|
+
addressId
|
|
17
|
+
}) => {
|
|
18
|
+
const command = db.update(tables.address).set({
|
|
19
|
+
lastSyncBlock
|
|
20
|
+
}).where(eq(tables.address.id, addressId)).returning();
|
|
21
|
+
return {
|
|
22
|
+
command
|
|
23
|
+
};
|
|
24
|
+
};
|
|
11
25
|
|
|
12
26
|
const updateAddressLastSyncCommand = (db, {
|
|
13
27
|
lastSyncAt,
|
|
@@ -28,9 +42,14 @@ const getAddressById = async (db, id) => {
|
|
|
28
42
|
return address;
|
|
29
43
|
};
|
|
30
44
|
|
|
45
|
+
const getContractAddresses = async (db, { connector }) => {
|
|
46
|
+
const addresses = await db.select().from(tables.tokens).where(eq(tables.tokens.connector, connector)).all();
|
|
47
|
+
return addresses;
|
|
48
|
+
};
|
|
49
|
+
|
|
31
50
|
const createTransactionCommand = (db, { transaction }) => {
|
|
32
51
|
const id = uuidv4();
|
|
33
|
-
const command = db.insert(tables.transaction).values({ ...transaction, id }).returning();
|
|
52
|
+
const command = db.insert(tables.transaction).values({ ...transaction, id }).onConflictDoNothing().returning();
|
|
34
53
|
return { command };
|
|
35
54
|
};
|
|
36
55
|
|
|
@@ -59,98 +78,86 @@ class BlockchainSyncAddressTransactions extends WorkflowEntrypoint {
|
|
|
59
78
|
`Blockchain address not found: ${addressId}.`
|
|
60
79
|
);
|
|
61
80
|
}
|
|
62
|
-
return
|
|
81
|
+
return {
|
|
82
|
+
...address2,
|
|
83
|
+
lastSyncBlock: address2.lastSyncBlock?.toString() ?? null
|
|
84
|
+
};
|
|
63
85
|
});
|
|
64
86
|
if (!address.lastSyncAt) {
|
|
65
|
-
throw new
|
|
87
|
+
throw new NonRetryableError(
|
|
88
|
+
`lastSyncedAt is not set for address: ${address}`
|
|
89
|
+
);
|
|
66
90
|
}
|
|
67
91
|
const transactions = await step.do(
|
|
68
|
-
|
|
92
|
+
`fetch address transactions`,
|
|
69
93
|
{
|
|
70
94
|
retries: { limit: 5, delay: 2e3, backoff: "constant" },
|
|
71
95
|
timeout: "30 seconds"
|
|
72
96
|
},
|
|
73
97
|
async () => {
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
})).data?.secretValue || "";
|
|
77
|
-
const client = createPublicClient({
|
|
78
|
-
chain: gnosisChiado,
|
|
79
|
-
transport: http(rpcUrl)
|
|
98
|
+
const tokens = await getContractAddresses(db, {
|
|
99
|
+
connector: address.connector
|
|
80
100
|
});
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const blockTimestamp = Number(block.timestamp);
|
|
96
|
-
const lastSyncedTimestampNum = typeof lastSyncedTimestamp === "number" ? lastSyncedTimestamp : Number(lastSyncedTimestamp);
|
|
97
|
-
if (blockTimestamp <= lastSyncedTimestampNum) {
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
for (const tx of block.transactions) {
|
|
101
|
-
if (typeof tx === "string" || !tx.to) continue;
|
|
102
|
-
if (tx.from.toLowerCase() === address.number.toLowerCase()) {
|
|
103
|
-
const receipt = await client.getTransactionReceipt({
|
|
104
|
-
hash: tx.hash
|
|
105
|
-
});
|
|
106
|
-
allTransactions.push({
|
|
107
|
-
hash: tx.hash,
|
|
108
|
-
from: tx.from,
|
|
109
|
-
to: tx.to,
|
|
110
|
-
value: tx.value.toString(),
|
|
111
|
-
blockNumber: block.number.toString(),
|
|
112
|
-
blockHash: block.hash,
|
|
113
|
-
gasUsed: receipt.gasUsed.toString(),
|
|
114
|
-
gasPrice: tx.gasPrice?.toString() ?? "",
|
|
115
|
-
timestamp: blockTimestamp,
|
|
116
|
-
status: receipt.status
|
|
117
|
-
});
|
|
101
|
+
if (!tokens || tokens.length === 0) {
|
|
102
|
+
throw new NonRetryableError(
|
|
103
|
+
`No contract addresses found for connector: ${address.connector}`
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
const connector = await initiateConnector({
|
|
107
|
+
chain: address.connector,
|
|
108
|
+
env: this.env,
|
|
109
|
+
tokens,
|
|
110
|
+
connectedAddresses: [
|
|
111
|
+
{
|
|
112
|
+
id: address.id,
|
|
113
|
+
number: address.number,
|
|
114
|
+
connector: address.connector
|
|
118
115
|
}
|
|
116
|
+
]
|
|
117
|
+
});
|
|
118
|
+
const result = await connector.getAllAddressTransactions({
|
|
119
|
+
address: address.number,
|
|
120
|
+
filter: {
|
|
121
|
+
fromBlock: address.lastSyncBlock ? BigInt(address.lastSyncBlock) : null
|
|
119
122
|
}
|
|
120
|
-
}
|
|
121
|
-
return
|
|
123
|
+
});
|
|
124
|
+
return {
|
|
125
|
+
transactions: result.transactions,
|
|
126
|
+
latestBlock: result.latestBlock.toString()
|
|
127
|
+
};
|
|
122
128
|
}
|
|
123
129
|
);
|
|
124
|
-
if (transactions.length > 0) {
|
|
130
|
+
if (transactions.transactions.length > 0) {
|
|
125
131
|
await step.do(
|
|
126
|
-
|
|
132
|
+
`process new transactions and update lastSyncAt`,
|
|
127
133
|
async () => {
|
|
128
|
-
const createCommands = transactions.map(
|
|
134
|
+
const createCommands = transactions.transactions.map(
|
|
129
135
|
(tx) => createTransactionCommand(db, { transaction: tx }).command
|
|
130
136
|
);
|
|
131
|
-
const eventsToEmit = transactions.map(
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
137
|
+
const eventsToEmit = transactions.transactions.map((tx) => ({
|
|
138
|
+
eventType: "BLOCKCHAIN_TRANSACTION",
|
|
139
|
+
blockchainTransaction: {
|
|
140
|
+
address: address.number,
|
|
141
|
+
hash: tx.hash,
|
|
142
|
+
from: tx.from,
|
|
143
|
+
to: tx.to,
|
|
144
|
+
value: tx.value,
|
|
145
|
+
blockNumber: tx.blockNumber,
|
|
146
|
+
blockHash: tx.blockHash,
|
|
147
|
+
gasUsed: tx.gasUsed,
|
|
148
|
+
gasPrice: tx.gasPrice,
|
|
149
|
+
timestamp: tx.timestamp,
|
|
150
|
+
status: tx.status,
|
|
151
|
+
decimals: tx.decimals,
|
|
152
|
+
connector: address.connector,
|
|
153
|
+
ticker: tx.ticker
|
|
154
|
+
},
|
|
155
|
+
metadata: {
|
|
156
|
+
correlationId: uuidv4(),
|
|
157
|
+
entityId: uuidv4(),
|
|
158
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
159
|
+
}
|
|
160
|
+
}));
|
|
154
161
|
const lastSyncMetadata = {
|
|
155
162
|
eventsEmitted: eventsToEmit.length
|
|
156
163
|
};
|
|
@@ -159,9 +166,17 @@ class BlockchainSyncAddressTransactions extends WorkflowEntrypoint {
|
|
|
159
166
|
lastSyncAt: now,
|
|
160
167
|
lastSyncMetadata
|
|
161
168
|
}).command;
|
|
169
|
+
const updateLastSyncBlockCommand = updateAddressLastSyncBlockCommand(db, {
|
|
170
|
+
addressId: address.id,
|
|
171
|
+
lastSyncBlock: BigInt(transactions.latestBlock)
|
|
172
|
+
}).command;
|
|
162
173
|
if (eventsToEmit.length) {
|
|
163
174
|
await db.batch(
|
|
164
|
-
asNonEmpty([
|
|
175
|
+
asNonEmpty([
|
|
176
|
+
updateLastSyncCommand,
|
|
177
|
+
updateLastSyncBlockCommand,
|
|
178
|
+
...createCommands
|
|
179
|
+
])
|
|
165
180
|
);
|
|
166
181
|
await pushToQueue(
|
|
167
182
|
this.env.QUEUE_BUS_QUEUE,
|
|
@@ -176,7 +191,7 @@ class BlockchainSyncAddressTransactions extends WorkflowEntrypoint {
|
|
|
176
191
|
);
|
|
177
192
|
}
|
|
178
193
|
await step.sleep(
|
|
179
|
-
|
|
194
|
+
`sleep until next sync`,
|
|
180
195
|
`${address.syncIntervalS} seconds`
|
|
181
196
|
);
|
|
182
197
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { base } from '@develit-io/backend-sdk';
|
|
2
|
+
import { sqliteTable, text, integer, blob, uniqueIndex } from 'drizzle-orm/sqlite-core';
|
|
3
|
+
import { a as CREDENTIALS_TYPES, C as CHAIN_KEYS } from './blockchain.CKh8Fs7w.mjs';
|
|
4
|
+
|
|
5
|
+
const address = sqliteTable("address", {
|
|
6
|
+
...base,
|
|
7
|
+
number: text("number").notNull(),
|
|
8
|
+
syncIntervalS: integer("sync_interval_s").notNull().default(600),
|
|
9
|
+
lastSyncBlock: blob("last_sync_block", { mode: "bigint" }),
|
|
10
|
+
lastSyncAt: integer("last_sync_at", { mode: "timestamp_ms" }),
|
|
11
|
+
lastSyncMetadata: text("last_sync_metadata", {
|
|
12
|
+
mode: "json"
|
|
13
|
+
}).$type(),
|
|
14
|
+
connector: text("connector").$type()
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const addressCredentials = sqliteTable("address_credentials", {
|
|
18
|
+
...base,
|
|
19
|
+
addressId: text("address_id").references(() => address.id, { onDelete: "restrict", onUpdate: "cascade" }).notNull(),
|
|
20
|
+
connector: text("connector", {
|
|
21
|
+
enum: CHAIN_KEYS
|
|
22
|
+
}).$type().notNull(),
|
|
23
|
+
type: text("type", {
|
|
24
|
+
enum: CREDENTIALS_TYPES
|
|
25
|
+
}).$type().notNull(),
|
|
26
|
+
value: text("value").notNull(),
|
|
27
|
+
expiresAt: integer("expires_at", { mode: "timestamp_ms" })
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const tokens = sqliteTable("tokens", {
|
|
31
|
+
...base,
|
|
32
|
+
smartContractAddress: text("smart_contract_address").$type().notNull(),
|
|
33
|
+
connector: text("connector").$type(),
|
|
34
|
+
ticker: text("ticker").notNull(),
|
|
35
|
+
decimals: integer("decimals").notNull(),
|
|
36
|
+
name: text("name")
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const transaction = sqliteTable(
|
|
40
|
+
"transaction",
|
|
41
|
+
{
|
|
42
|
+
...base,
|
|
43
|
+
hash: text("hash"),
|
|
44
|
+
from: text("from"),
|
|
45
|
+
to: text("to"),
|
|
46
|
+
value: text("value"),
|
|
47
|
+
blockNumber: text("block_number"),
|
|
48
|
+
blockHash: text("blockHash"),
|
|
49
|
+
gasUsed: text("gasUsed"),
|
|
50
|
+
gasPrice: text("gasPrice"),
|
|
51
|
+
timestamp: integer("timestamp"),
|
|
52
|
+
status: text("status"),
|
|
53
|
+
decimals: integer("decimals"),
|
|
54
|
+
connector: text("connector").$type(),
|
|
55
|
+
ticker: text("ticker")
|
|
56
|
+
},
|
|
57
|
+
(t) => [uniqueIndex("transaction_hash_unique").on(t.hash)]
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const schema = {
|
|
61
|
+
__proto__: null,
|
|
62
|
+
address: address,
|
|
63
|
+
addressCredentials: addressCredentials,
|
|
64
|
+
tokens: tokens,
|
|
65
|
+
transaction: transaction
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export { address as a, addressCredentials as b, transaction as c, schema as s, tokens as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { s as schema } from './blockchain.
|
|
2
|
+
import { s as schema } from './blockchain.DUhjXgba.cjs';
|
|
3
3
|
|
|
4
4
|
declare const getBlockInputSchema: z.ZodObject<{
|
|
5
5
|
chain: z.ZodEnum<{
|
|
@@ -12,9 +12,9 @@ declare const getBlockInputSchema: z.ZodObject<{
|
|
|
12
12
|
SCROLL: "SCROLL";
|
|
13
13
|
}>;
|
|
14
14
|
blockTag: z.ZodOptional<z.ZodEnum<{
|
|
15
|
-
pending: "pending";
|
|
16
15
|
latest: "latest";
|
|
17
16
|
earliest: "earliest";
|
|
17
|
+
pending: "pending";
|
|
18
18
|
safe: "safe";
|
|
19
19
|
finalized: "finalized";
|
|
20
20
|
}>>;
|
|
@@ -93,9 +93,9 @@ declare const getTransactionOutputSchema: z.ZodObject<{
|
|
|
93
93
|
nonce: z.ZodNumber;
|
|
94
94
|
transactionIndex: z.ZodNullable<z.ZodNumber>;
|
|
95
95
|
status: z.ZodEnum<{
|
|
96
|
+
pending: "pending";
|
|
96
97
|
success: "success";
|
|
97
98
|
reverted: "reverted";
|
|
98
|
-
pending: "pending";
|
|
99
99
|
}>;
|
|
100
100
|
gasUsed: z.ZodNullable<z.ZodString>;
|
|
101
101
|
timestamp: z.ZodNullable<z.ZodNumber>;
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { workflowInstanceStatusSchema } from '@develit-io/backend-sdk';
|
|
3
3
|
|
|
4
|
+
const CHAIN_KEYS = [
|
|
5
|
+
"ARBITRUM",
|
|
6
|
+
"AVALANCHE",
|
|
7
|
+
"BASE",
|
|
8
|
+
"ETHEREUM",
|
|
9
|
+
"GNOSIS",
|
|
10
|
+
"OPTIMISM",
|
|
11
|
+
"SCROLL"
|
|
12
|
+
];
|
|
13
|
+
const CREDENTIALS_TYPES = ["PRIVATE_KEY"];
|
|
14
|
+
|
|
4
15
|
const chainSchema = z.enum([
|
|
5
16
|
"ARBITRUM",
|
|
6
17
|
"AVALANCHE",
|
|
@@ -84,4 +95,4 @@ const syncAddressOutputSchema = z.object({
|
|
|
84
95
|
details: workflowInstanceStatusSchema
|
|
85
96
|
});
|
|
86
97
|
|
|
87
|
-
export {
|
|
98
|
+
export { CHAIN_KEYS as C, CREDENTIALS_TYPES as a, getBlockOutputSchema as b, chainSchema as c, getTransactionInputSchema as d, getTransactionOutputSchema as e, syncAddressOutputSchema as f, getBlockInputSchema as g, syncAddressInputSchema as s };
|
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
const zod = require('zod');
|
|
4
4
|
const backendSdk = require('@develit-io/backend-sdk');
|
|
5
5
|
|
|
6
|
+
const CHAIN_KEYS = [
|
|
7
|
+
"ARBITRUM",
|
|
8
|
+
"AVALANCHE",
|
|
9
|
+
"BASE",
|
|
10
|
+
"ETHEREUM",
|
|
11
|
+
"GNOSIS",
|
|
12
|
+
"OPTIMISM",
|
|
13
|
+
"SCROLL"
|
|
14
|
+
];
|
|
15
|
+
const CREDENTIALS_TYPES = ["PRIVATE_KEY"];
|
|
16
|
+
|
|
6
17
|
const chainSchema = zod.z.enum([
|
|
7
18
|
"ARBITRUM",
|
|
8
19
|
"AVALANCHE",
|
|
@@ -86,6 +97,8 @@ const syncAddressOutputSchema = zod.z.object({
|
|
|
86
97
|
details: backendSdk.workflowInstanceStatusSchema
|
|
87
98
|
});
|
|
88
99
|
|
|
100
|
+
exports.CHAIN_KEYS = CHAIN_KEYS;
|
|
101
|
+
exports.CREDENTIALS_TYPES = CREDENTIALS_TYPES;
|
|
89
102
|
exports.chainSchema = chainSchema;
|
|
90
103
|
exports.getBlockInputSchema = getBlockInputSchema;
|
|
91
104
|
exports.getBlockOutputSchema = getBlockOutputSchema;
|