tapimo 0.0.2 → 0.1.0
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/README.md +11 -2
- package/dist/ApiKey.d.ts +12 -11
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +10 -12
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +139 -0
- package/dist/ApiKeys.d.ts.map +1 -0
- package/dist/ApiKeys.js +166 -0
- package/dist/ApiKeys.js.map +1 -0
- package/dist/App.d.ts +920 -910
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +36 -12
- package/dist/App.js.map +1 -1
- package/dist/Handler.d.ts +86 -0
- package/dist/Handler.d.ts.map +1 -0
- package/dist/Handler.js +83 -0
- package/dist/Handler.js.map +1 -0
- package/dist/Scope.d.ts +4 -1
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +5 -1
- package/dist/Scope.js.map +1 -1
- package/dist/Webhooks.d.ts +3 -5
- package/dist/Webhooks.d.ts.map +1 -1
- package/dist/Webhooks.js +9 -2
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/Access.d.ts +1 -3
- package/dist/admin/Access.d.ts.map +1 -1
- package/dist/admin/Access.js +1 -3
- package/dist/admin/Access.js.map +1 -1
- package/dist/admin/App.d.ts +98 -209
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +2 -4
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +7 -5
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +8 -9
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/scopes.d.ts +3 -0
- package/dist/admin/apps/scopes.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +101 -215
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.js +17 -38
- package/dist/admin/apps/verified-tokens.js.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.js +1 -1
- package/dist/apps/balances.d.ts +2 -2
- package/dist/apps/receipts.d.ts +43 -43
- package/dist/apps/tokens.d.ts +454 -454
- package/dist/apps/transactions.d.ts +43 -43
- package/dist/apps/transfers.d.ts +29 -29
- package/dist/apps/webhooks.d.ts +5 -2
- package/dist/apps/webhooks.d.ts.map +1 -1
- package/dist/apps/webhooks.js +38 -34
- package/dist/apps/webhooks.js.map +1 -1
- package/dist/{Cli.d.ts → cli/Cli.d.ts} +13 -2
- package/dist/cli/Cli.d.ts.map +1 -0
- package/dist/cli/Cli.js +19 -0
- package/dist/cli/Cli.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +4 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/admin.d.ts +15 -0
- package/dist/cli/commands/admin.d.ts.map +1 -0
- package/dist/cli/commands/admin.js +60 -0
- package/dist/cli/commands/admin.js.map +1 -0
- package/dist/cloudflare.d.ts +7 -0
- package/dist/cloudflare.d.ts.map +1 -1
- package/dist/cloudflare.js +9 -0
- package/dist/cloudflare.js.map +1 -1
- package/dist/db/Db.d.ts +103 -0
- package/dist/db/Db.d.ts.map +1 -0
- package/dist/db/Db.js +274 -0
- package/dist/db/Db.js.map +1 -0
- package/dist/db/Schema.d.ts +88 -0
- package/dist/db/Schema.d.ts.map +1 -0
- package/dist/db/Schema.js +130 -0
- package/dist/db/Schema.js.map +1 -0
- package/dist/db/tables/organizations.d.ts +79 -0
- package/dist/db/tables/organizations.d.ts.map +1 -0
- package/dist/db/tables/organizations.js +81 -0
- package/dist/db/tables/organizations.js.map +1 -0
- package/dist/db/tables/verifiedTokens.d.ts +53 -0
- package/dist/db/tables/verifiedTokens.d.ts.map +1 -0
- package/dist/db/tables/verifiedTokens.js +74 -0
- package/dist/db/tables/verifiedTokens.js.map +1 -0
- package/dist/db/tables/webhookDeliveries.d.ts +71 -0
- package/dist/db/tables/webhookDeliveries.d.ts.map +1 -0
- package/dist/db/tables/webhookDeliveries.js +119 -0
- package/dist/db/tables/webhookDeliveries.js.map +1 -0
- package/dist/db/tables/webhookSubscriptions.d.ts +158 -0
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -0
- package/dist/db/tables/webhookSubscriptions.js +272 -0
- package/dist/db/tables/webhookSubscriptions.js.map +1 -0
- package/dist/handlers/internal/executionError.d.ts +25 -0
- package/dist/handlers/internal/executionError.d.ts.map +1 -0
- package/dist/handlers/internal/executionError.js +184 -0
- package/dist/handlers/internal/executionError.js.map +1 -0
- package/dist/handlers/internal/multisig.d.ts +237 -0
- package/dist/handlers/internal/multisig.d.ts.map +1 -0
- package/dist/handlers/internal/multisig.js +567 -0
- package/dist/handlers/internal/multisig.js.map +1 -0
- package/dist/handlers/internal/requestListener.d.ts +124 -0
- package/dist/handlers/internal/requestListener.d.ts.map +1 -0
- package/dist/handlers/internal/requestListener.js +173 -0
- package/dist/handlers/internal/requestListener.js.map +1 -0
- package/dist/handlers/internal/sponsorship.d.ts +83 -0
- package/dist/handlers/internal/sponsorship.d.ts.map +1 -0
- package/dist/handlers/internal/sponsorship.js +103 -0
- package/dist/handlers/internal/sponsorship.js.map +1 -0
- package/dist/handlers/internal/types.d.ts +284 -0
- package/dist/handlers/internal/types.d.ts.map +1 -0
- package/dist/handlers/internal/types.js +2 -0
- package/dist/handlers/internal/types.js.map +1 -0
- package/dist/handlers/internal/utils.d.ts +34 -0
- package/dist/handlers/internal/utils.d.ts.map +1 -0
- package/dist/handlers/internal/utils.js +131 -0
- package/dist/handlers/internal/utils.js.map +1 -0
- package/dist/handlers/relay.d.ts +119 -0
- package/dist/handlers/relay.d.ts.map +1 -0
- package/dist/handlers/relay.js +1264 -0
- package/dist/handlers/relay.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/internal/Auth.d.ts +16 -10
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +72 -12
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/RpcSchema.d.ts +10 -0
- package/dist/internal/RpcSchema.d.ts.map +1 -0
- package/dist/internal/RpcSchema.js +2 -0
- package/dist/internal/RpcSchema.js.map +1 -0
- package/dist/internal/Store.d.ts +42 -3
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +65 -3
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/VerifiedTokens.d.ts +15 -34
- package/dist/internal/VerifiedTokens.d.ts.map +1 -1
- package/dist/internal/VerifiedTokens.js +115 -159
- package/dist/internal/VerifiedTokens.js.map +1 -1
- package/dist/internal/Webhooks.d.ts +49 -35
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +92 -205
- package/dist/internal/Webhooks.js.map +1 -1
- package/package.json +7 -2
- package/src/ApiKey.test.ts +3 -3
- package/src/ApiKey.ts +10 -12
- package/src/ApiKeys.test.ts +175 -0
- package/src/ApiKeys.ts +205 -0
- package/src/App.test-d.ts +1 -1
- package/src/App.test.ts +10768 -351
- package/src/App.ts +79 -36
- package/src/Client.test-d.ts +1 -1
- package/src/Handler.ts +154 -0
- package/src/Scope.ts +5 -1
- package/src/Webhooks.test.ts +8 -7
- package/src/Webhooks.ts +11 -5
- package/src/admin/Access.ts +1 -3
- package/src/admin/App.ts +19 -24
- package/src/admin/apps/api-keys.test.ts +19 -18
- package/src/admin/apps/api-keys.ts +8 -9
- package/src/admin/apps/scopes.test.ts +4 -0
- package/src/admin/apps/verified-tokens.test.ts +3 -30
- package/src/admin/apps/verified-tokens.ts +17 -36
- package/src/admin/ui.generated.ts +1 -1
- package/src/apps/balances.test.ts +4 -3
- package/src/apps/blocks.test.ts +1 -1
- package/src/apps/exchanges.test.ts +1 -1
- package/src/apps/indexer.test.ts +1 -1
- package/src/apps/receipts.test.ts +1 -1
- package/src/apps/rpc.test.ts +100 -10
- package/src/apps/tokenlist.test.ts +5 -7
- package/src/apps/tokens.test.ts +4 -3
- package/src/apps/transactions.test.ts +1 -1
- package/src/apps/transfers.test.ts +1 -1
- package/src/apps/verified-tokens.test.ts +24 -12
- package/src/apps/webhooks.test.ts +130 -143
- package/src/apps/webhooks.ts +45 -47
- package/src/{Cli.test.ts → cli/Cli.test.ts} +10 -9
- package/src/{Cli.ts → cli/Cli.ts} +16 -9
- package/src/cli/bin.ts +4 -0
- package/src/cli/commands/admin.test.ts +71 -0
- package/src/cli/commands/admin.ts +60 -0
- package/src/cloudflare.ts +10 -0
- package/src/db/Db.test.ts +84 -0
- package/src/db/Db.ts +383 -0
- package/src/db/Schema.ts +164 -0
- package/src/db/tables/organizations.test.ts +124 -0
- package/src/db/tables/organizations.ts +127 -0
- package/src/db/tables/verifiedTokens.ts +111 -0
- package/src/db/tables/webhookDeliveries.ts +159 -0
- package/src/db/tables/webhookSubscriptions.ts +358 -0
- package/src/handlers/internal/executionError.ts +205 -0
- package/src/handlers/internal/multisig.localnet.test.ts +146 -0
- package/src/handlers/internal/multisig.test.ts +744 -0
- package/src/handlers/internal/multisig.ts +858 -0
- package/src/handlers/internal/relay.localnet.test.ts +2035 -0
- package/src/handlers/internal/requestListener.ts +273 -0
- package/src/handlers/internal/sponsorship.ts +186 -0
- package/src/handlers/internal/types.ts +378 -0
- package/src/handlers/internal/utils.ts +153 -0
- package/src/handlers/relay.ts +1605 -0
- package/src/index.ts +4 -2
- package/src/internal/Auth.test.ts +21 -21
- package/src/internal/Auth.ts +92 -19
- package/src/internal/RateLimit.test.ts +1 -1
- package/src/internal/RpcSchema.ts +10 -0
- package/src/internal/Store.test.ts +98 -10
- package/src/internal/Store.ts +112 -6
- package/src/internal/VerifiedTokens.test.ts +99 -115
- package/src/internal/VerifiedTokens.ts +123 -175
- package/src/internal/Webhooks.test.ts +107 -107
- package/src/internal/Webhooks.ts +102 -220
- package/dist/ApiKeySource.d.ts +0 -166
- package/dist/ApiKeySource.d.ts.map +0 -1
- package/dist/ApiKeySource.js +0 -234
- package/dist/ApiKeySource.js.map +0 -1
- package/dist/Cli.d.ts.map +0 -1
- package/dist/Cli.js +0 -13
- package/dist/Cli.js.map +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000000.svg +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000001.svg +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000002.svg +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000003.svg +0 -1
- package/seeds/31318/verified-tokens.json +0 -30
- package/seeds/4217/icons/0x20c0000000000000000000000000000000000000.svg +0 -25
- package/seeds/4217/icons/0x20c000000000000000000000048c8f36df1c9a4a.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000000520792dcccccccc.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000000a6da882d075a4c3.svg +0 -4
- package/seeds/4217/icons/0x20c000000000000000000000111111111e910f0f.svg +0 -30
- package/seeds/4217/icons/0x20c00000000000000000000014f22ca97301eb73.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000001621e21f71cf12fb.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000002f52d5cc21a3207b.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000003158081efd85bfc2.svg +0 -11
- package/seeds/4217/icons/0x20c0000000000000000000003554d28269e0f3c2.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000383a23bacb546ab9.svg +0 -1
- package/seeds/4217/icons/0x20c00000000000000000000042109aef2f8b28e1.png +0 -0
- package/seeds/4217/icons/0x20c0000000000000000000005c0bac7cef389a11.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000006fd9a167923ba194.png +0 -0
- package/seeds/4217/icons/0x20c0000000000000000000007f7ba549dd0251b9.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000008191667423f70e67.svg +0 -5
- package/seeds/4217/icons/0x20c0000000000000000000008ee4fcff88888888.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000009a4a4b17e0dc6651.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000ab02d39df30bd17e.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000ae247a1130450f09.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000aeed2ec36a54d0e5.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000b9537d11c60e8b50.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000bd95bfb69fbe6ce3.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000c412ec89d0c08be5.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000f047dd7018e50367.png +0 -0
- package/seeds/4217/verified-tokens.json +0 -177
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000000.svg +0 -25
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000001.svg +0 -1
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000002.svg +0 -1
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000003.svg +0 -1
- package/seeds/42431/icons/0x20c0000000000000000000009e8d7eb59b783726.svg +0 -1
- package/seeds/42431/icons/0x20c000000000000000000000d72572838bbee59c.svg +0 -1
- package/seeds/42431/verified-tokens.json +0 -44
- package/seeds/openrpc/README.md +0 -27
- package/seeds/openrpc/execution-apis.json +0 -8989
- package/src/ApiKeySource.test-d.ts +0 -11
- package/src/ApiKeySource.test.ts +0 -295
- package/src/ApiKeySource.ts +0 -303
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { MultisigConfig, SignatureEnvelope, TxEnvelopeTempo } from 'ox/tempo'
|
|
2
|
+
import { fillTransaction, getTransactionReceipt, sendRawTransactionSync } from 'viem/actions'
|
|
3
|
+
import { Account } from 'viem/tempo'
|
|
4
|
+
|
|
5
|
+
import * as Relay from '../../../test/Relay.js'
|
|
6
|
+
import * as Store from '../../internal/Store.js'
|
|
7
|
+
|
|
8
|
+
const owner_1 = Relay.accounts[1]!
|
|
9
|
+
const owner_2 = Relay.accounts[2]!
|
|
10
|
+
const feePayer = Relay.accounts[0]!
|
|
11
|
+
|
|
12
|
+
// Skipped: the localnet node images currently available (including the same
|
|
13
|
+
// `ghcr.io/tempoxyz/tempo:latest` the accounts suite uses) reject the multisig
|
|
14
|
+
// signed-transaction envelope with "failed to decode signed transaction". This
|
|
15
|
+
// test fails identically in the accounts repo today; it only passes against a
|
|
16
|
+
// node build that supports the multisig envelope. Re-enable once such an image
|
|
17
|
+
// is pinned here.
|
|
18
|
+
describe.skip('relay multisig', () => {
|
|
19
|
+
const store = Store.memory()
|
|
20
|
+
let client: ReturnType<typeof Relay.getClient>
|
|
21
|
+
let server: Relay.Server
|
|
22
|
+
|
|
23
|
+
beforeAll(async () => {
|
|
24
|
+
server = await Relay.createServer(
|
|
25
|
+
(
|
|
26
|
+
await Relay.relay({
|
|
27
|
+
feePayer: { account: feePayer },
|
|
28
|
+
multisig: { store },
|
|
29
|
+
})
|
|
30
|
+
).listener,
|
|
31
|
+
)
|
|
32
|
+
client = Relay.getClient({ url: server.url })
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
afterAll(() => {
|
|
36
|
+
server.close()
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('behavior: collects approvals and resolves operation-id receipt aliases on localnet', async () => {
|
|
40
|
+
const account = Account.fromMultisig({
|
|
41
|
+
threshold: 2,
|
|
42
|
+
owners: [
|
|
43
|
+
{ owner: owner_1.address, weight: 1 },
|
|
44
|
+
{ owner: owner_2.address, weight: 1 },
|
|
45
|
+
],
|
|
46
|
+
})
|
|
47
|
+
const { transaction } = await fillTransaction(client, {
|
|
48
|
+
account,
|
|
49
|
+
to: account.address,
|
|
50
|
+
value: 0n,
|
|
51
|
+
} as never)
|
|
52
|
+
const { account: _account, gas, ...filled } = transaction as Record<string, unknown>
|
|
53
|
+
const request: Record<string, unknown> = {
|
|
54
|
+
...filled,
|
|
55
|
+
feePayerSignature: null,
|
|
56
|
+
gas: typeof gas === 'bigint' ? gas + 100_000n : gas,
|
|
57
|
+
}
|
|
58
|
+
const {
|
|
59
|
+
_capabilities,
|
|
60
|
+
account: _account_request,
|
|
61
|
+
data,
|
|
62
|
+
from: _from,
|
|
63
|
+
multisig: _multisig,
|
|
64
|
+
signature: _signature,
|
|
65
|
+
signatures: _signatures,
|
|
66
|
+
to,
|
|
67
|
+
value,
|
|
68
|
+
...transaction_request
|
|
69
|
+
} = request
|
|
70
|
+
const calls = (() => {
|
|
71
|
+
if ('calls' in transaction_request) return transaction_request['calls']
|
|
72
|
+
if (typeof to !== 'string') return undefined
|
|
73
|
+
return [
|
|
74
|
+
{
|
|
75
|
+
...(typeof data === 'string' ? { data } : {}),
|
|
76
|
+
to,
|
|
77
|
+
value: typeof value === 'bigint' ? value : 0n,
|
|
78
|
+
},
|
|
79
|
+
]
|
|
80
|
+
})()
|
|
81
|
+
const envelope = TxEnvelopeTempo.from({ ...transaction_request, calls } as never)
|
|
82
|
+
const payload = TxEnvelopeTempo.getSignPayload(envelope)
|
|
83
|
+
const genesisConfigId = MultisigConfig.toId(account.config)
|
|
84
|
+
const id = MultisigConfig.getSignPayload({
|
|
85
|
+
account: account.address,
|
|
86
|
+
genesisConfigId,
|
|
87
|
+
payload,
|
|
88
|
+
})
|
|
89
|
+
const signature_1 = await signApproval({ digest: id, signer: owner_1 })
|
|
90
|
+
const signature_2 = await signApproval({ digest: id, signer: owner_2 })
|
|
91
|
+
|
|
92
|
+
const pending = await client.request({
|
|
93
|
+
method: 'eth_sendRawTransactionSync',
|
|
94
|
+
params: [serializeTransaction({ account, envelope, signatures: [signature_1] })],
|
|
95
|
+
} as never)
|
|
96
|
+
|
|
97
|
+
expect(pending).toMatchInlineSnapshot(`"${id}"`)
|
|
98
|
+
await expect(
|
|
99
|
+
client.request({ method: 'eth_getTransactionReceipt', params: [id] }),
|
|
100
|
+
).resolves.toMatchInlineSnapshot(`null`)
|
|
101
|
+
|
|
102
|
+
const receipt = await sendRawTransactionSync(client, {
|
|
103
|
+
serializedTransaction: serializeTransaction({ account, envelope, signatures: [signature_2] }),
|
|
104
|
+
})
|
|
105
|
+
const hash = receipt.transactionHash
|
|
106
|
+
if (!hash) throw new Error('Expected multisig transaction hash.')
|
|
107
|
+
|
|
108
|
+
expect(hash === id).toMatchInlineSnapshot(`false`)
|
|
109
|
+
expect(receipt).toMatchObject({
|
|
110
|
+
status: 'success',
|
|
111
|
+
})
|
|
112
|
+
await expect(getTransactionReceipt(client, { hash: id })).resolves.toMatchObject({
|
|
113
|
+
transactionHash: hash,
|
|
114
|
+
})
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
async function signApproval(options: { digest: `0x${string}`; signer: typeof owner_1 }) {
|
|
119
|
+
const { digest, signer } = options
|
|
120
|
+
return SignatureEnvelope.serialize(SignatureEnvelope.from(await signer.sign({ hash: digest })))
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function serializeTransaction(options: {
|
|
124
|
+
account: ReturnType<typeof Account.fromMultisig>
|
|
125
|
+
envelope: ReturnType<typeof TxEnvelopeTempo.from>
|
|
126
|
+
signatures: readonly `0x${string}`[]
|
|
127
|
+
}) {
|
|
128
|
+
const { account, envelope } = options
|
|
129
|
+
const payload = TxEnvelopeTempo.getSignPayload(envelope)
|
|
130
|
+
const genesisConfigId = MultisigConfig.toId(account.config)
|
|
131
|
+
const signatures = SignatureEnvelope.sortMultisigApprovals({
|
|
132
|
+
account: account.address,
|
|
133
|
+
genesisConfigId,
|
|
134
|
+
payload,
|
|
135
|
+
signatures: options.signatures.map((signature) => SignatureEnvelope.from(signature)),
|
|
136
|
+
})
|
|
137
|
+
return TxEnvelopeTempo.serialize(envelope, {
|
|
138
|
+
feePayerSignature: undefined,
|
|
139
|
+
signature: SignatureEnvelope.from({
|
|
140
|
+
account: account.address,
|
|
141
|
+
genesisConfigId,
|
|
142
|
+
init: account.config,
|
|
143
|
+
signatures,
|
|
144
|
+
}),
|
|
145
|
+
})
|
|
146
|
+
}
|