@effectstream/sm 0.100.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/Stm.ts +88 -0
- package/delegate-wallet.ts +431 -0
- package/mod.ts +4 -0
- package/package.json +27 -0
- package/primitives/Primitive.ts +80 -0
- package/primitives/PrimitiveRegistry.ts +59 -0
- package/primitives/mod.ts +5 -0
- package/primitives/processing.ts +72 -0
- package/primitives/src/README.md +3 -0
- package/primitives/src/avail-generic/avail-generic-grammar.ts +5 -0
- package/primitives/src/avail-generic/avail-primitive.ts +103 -0
- package/primitives/src/bitcoin-address/bitcoin-grammar.ts +16 -0
- package/primitives/src/bitcoin-address/bitcoin-primitive.ts +113 -0
- package/primitives/src/builtin.ts +47 -0
- package/primitives/src/celestia-generic/celestia-generic-grammar.ts +5 -0
- package/primitives/src/celestia-generic/celestia-primitive.ts +97 -0
- package/primitives/src/evm-effectstream-l2/effectstream-l2-abi.ts +1 -0
- package/primitives/src/evm-effectstream-l2/effectstream-l2-primitive.ts +484 -0
- package/primitives/src/evm-erc1155/erc1155-abi.ts +1 -0
- package/primitives/src/evm-erc1155/erc1155-grammar.ts +13 -0
- package/primitives/src/evm-erc1155/erc1155-ivm.ts +104 -0
- package/primitives/src/evm-erc1155/erc1155-primitive.ts +242 -0
- package/primitives/src/evm-erc20/erc20-abi.ts +1 -0
- package/primitives/src/evm-erc20/erc20-grammar.ts +7 -0
- package/primitives/src/evm-erc20/erc20-ivm.ts +93 -0
- package/primitives/src/evm-erc20/erc20-primitive.test.ts +123 -0
- package/primitives/src/evm-erc20/erc20-primitive.ts +152 -0
- package/primitives/src/evm-erc721/erc721-abi.ts +1 -0
- package/primitives/src/evm-erc721/erc721-grammar.ts +9 -0
- package/primitives/src/evm-erc721/erc721-ivm.ts +85 -0
- package/primitives/src/evm-erc721/erc721-primitive.ts +149 -0
- package/primitives/src/evm-generic/evm-generic-primitive.ts +124 -0
- package/primitives/src/grammar.ts +34 -0
- package/primitives/src/midnight-generic/midnight-genetic-grammar.ts +8 -0
- package/primitives/src/midnight-generic/midnight-genetic.ts +271 -0
- package/primitives/src/midnight-nullifier/midnight-nullifier-grammar.ts +8 -0
- package/primitives/src/midnight-nullifier/midnight-nullifier.ts +114 -0
- package/primitives/src/mod.ts +81 -0
- package/primitives/src/near-account-watch/near-account-watch-grammar.ts +10 -0
- package/primitives/src/near-account-watch/near-account-watch-primitive.ts +106 -0
- package/primitives/src/near-generic/near-generic-grammar.ts +5 -0
- package/primitives/src/near-generic/near-generic-primitive.ts +105 -0
- package/primitives/src/near-intent/near-intent-grammar.ts +10 -0
- package/primitives/src/near-intent/near-intent-ivm.ts +71 -0
- package/primitives/src/near-intent/near-intent-primitive.ts +149 -0
- package/primitives/src/near-intent/near-intent-token-id-parser.ts +47 -0
- package/primitives/src/near-nep141/nep141-grammar.ts +7 -0
- package/primitives/src/near-nep141/nep141-ivm.ts +70 -0
- package/primitives/src/near-nep141/nep141-primitive.ts +117 -0
- package/primitives/src/near-nep171/nep171-grammar.ts +8 -0
- package/primitives/src/near-nep171/nep171-ivm.ts +71 -0
- package/primitives/src/near-nep171/nep171-primitive.ts +138 -0
- package/primitives/src/near-nep245/nep245-grammar.ts +11 -0
- package/primitives/src/near-nep245/nep245-ivm.ts +84 -0
- package/primitives/src/near-nep245/nep245-primitive.ts +147 -0
- package/primitives/src/utxorpc-generic/utxorpc-generic-grammar.ts +6 -0
- package/primitives/src/utxorpc-generic/utxorpc-generic.ts +88 -0
- package/primitives/types.ts +14 -0
- package/types.ts +28 -0
- package/verify-signature.ts +51 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PrimitiveTypeMidnightGeneric,
|
|
3
|
+
PrimitiveTypeMidnightNullifier,
|
|
4
|
+
PrimitiveTypeEVMEffectstreamL2,
|
|
5
|
+
PrimitiveTypeEVMERC721,
|
|
6
|
+
PrimitiveTypeEVMERC20,
|
|
7
|
+
PrimitiveTypeAvailGeneric,
|
|
8
|
+
PrimitiveTypeEVMERC1155,
|
|
9
|
+
PrimitiveTypeBitcoinAddress,
|
|
10
|
+
PrimitiveTypeUtxorpcGeneric,
|
|
11
|
+
PrimitiveTypeCelestiaGeneric,
|
|
12
|
+
PrimitiveTypeNEARNEP141,
|
|
13
|
+
PrimitiveTypeNEARNEP171,
|
|
14
|
+
PrimitiveTypeNEARNEP245,
|
|
15
|
+
PrimitiveTypeNEARIntent,
|
|
16
|
+
PrimitiveTypeNEARGeneric,
|
|
17
|
+
PrimitiveTypeNEARAccountWatch,
|
|
18
|
+
// PrimitiveTypeEVMGeneric,
|
|
19
|
+
} from "./builtin.ts";
|
|
20
|
+
|
|
21
|
+
import { MidnightGenericPrimitive } from "./midnight-generic/midnight-genetic.ts";
|
|
22
|
+
import { MidnightNullifierPrimitive } from "./midnight-nullifier/midnight-nullifier.ts";
|
|
23
|
+
import { EffectstreamL2Primitive } from "./evm-effectstream-l2/effectstream-l2-primitive.ts";
|
|
24
|
+
import { Erc721Primitive } from "./evm-erc721/erc721-primitive.ts";
|
|
25
|
+
import { Erc20Primitive } from "./evm-erc20/erc20-primitive.ts";
|
|
26
|
+
import { AvailGenericPrimitive } from "./avail-generic/avail-primitive.ts";
|
|
27
|
+
import { Erc1155Primitive } from "./evm-erc1155/erc1155-primitive.ts";
|
|
28
|
+
import { BitcoinAddressPrimitive } from "./bitcoin-address/bitcoin-primitive.ts";
|
|
29
|
+
import { UtxorpcGenericPrimitive } from "./utxorpc-generic/utxorpc-generic.ts";
|
|
30
|
+
import { CelestiaGenericPrimitive } from "./celestia-generic/celestia-primitive.ts";
|
|
31
|
+
import { Nep141Primitive } from "./near-nep141/nep141-primitive.ts";
|
|
32
|
+
import { Nep171Primitive } from "./near-nep171/nep171-primitive.ts";
|
|
33
|
+
import { Nep245Primitive } from "./near-nep245/nep245-primitive.ts";
|
|
34
|
+
import { NearIntentPrimitive } from "./near-intent/near-intent-primitive.ts";
|
|
35
|
+
import { NearGenericPrimitive } from "./near-generic/near-generic-primitive.ts";
|
|
36
|
+
import { NearAccountWatchPrimitive } from "./near-account-watch/near-account-watch-primitive.ts";
|
|
37
|
+
// import { EvmGenericPrimitive } from "./evm-generic/evm-generic-primitive.ts";
|
|
38
|
+
|
|
39
|
+
const builtInPrimitivesMap = {
|
|
40
|
+
[PrimitiveTypeMidnightGeneric]: MidnightGenericPrimitive,
|
|
41
|
+
[PrimitiveTypeMidnightNullifier]: MidnightNullifierPrimitive,
|
|
42
|
+
[PrimitiveTypeEVMEffectstreamL2]: EffectstreamL2Primitive,
|
|
43
|
+
[PrimitiveTypeEVMERC721]: Erc721Primitive,
|
|
44
|
+
[PrimitiveTypeEVMERC20]: Erc20Primitive,
|
|
45
|
+
[PrimitiveTypeAvailGeneric]: AvailGenericPrimitive,
|
|
46
|
+
[PrimitiveTypeEVMERC1155]: Erc1155Primitive,
|
|
47
|
+
[PrimitiveTypeBitcoinAddress]: BitcoinAddressPrimitive,
|
|
48
|
+
[PrimitiveTypeUtxorpcGeneric]: UtxorpcGenericPrimitive,
|
|
49
|
+
[PrimitiveTypeCelestiaGeneric]: CelestiaGenericPrimitive,
|
|
50
|
+
[PrimitiveTypeNEARNEP141]: Nep141Primitive,
|
|
51
|
+
[PrimitiveTypeNEARNEP171]: Nep171Primitive,
|
|
52
|
+
[PrimitiveTypeNEARNEP245]: Nep245Primitive,
|
|
53
|
+
[PrimitiveTypeNEARIntent]: NearIntentPrimitive,
|
|
54
|
+
[PrimitiveTypeNEARGeneric]: NearGenericPrimitive,
|
|
55
|
+
[PrimitiveTypeNEARAccountWatch]: NearAccountWatchPrimitive,
|
|
56
|
+
// [PrimitiveTypeEVMGeneric]: EvmGenericPrimitive,
|
|
57
|
+
} as const;
|
|
58
|
+
|
|
59
|
+
export {
|
|
60
|
+
// Built-in Primitives Map
|
|
61
|
+
builtInPrimitivesMap,
|
|
62
|
+
|
|
63
|
+
// Built-in Primitives
|
|
64
|
+
MidnightGenericPrimitive,
|
|
65
|
+
MidnightNullifierPrimitive,
|
|
66
|
+
EffectstreamL2Primitive,
|
|
67
|
+
Erc721Primitive,
|
|
68
|
+
Erc20Primitive,
|
|
69
|
+
AvailGenericPrimitive,
|
|
70
|
+
Erc1155Primitive,
|
|
71
|
+
BitcoinAddressPrimitive,
|
|
72
|
+
UtxorpcGenericPrimitive,
|
|
73
|
+
CelestiaGenericPrimitive,
|
|
74
|
+
Nep141Primitive,
|
|
75
|
+
Nep171Primitive,
|
|
76
|
+
Nep245Primitive,
|
|
77
|
+
NearIntentPrimitive,
|
|
78
|
+
NearGenericPrimitive,
|
|
79
|
+
NearAccountWatchPrimitive,
|
|
80
|
+
// EvmGenericPrimitive,
|
|
81
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
|
|
3
|
+
export const nearAccountWatchGrammar = [
|
|
4
|
+
['signer_id', Type.String()],
|
|
5
|
+
['receiver_id', Type.String()],
|
|
6
|
+
['method_name', Type.String()],
|
|
7
|
+
['args', Type.String()],
|
|
8
|
+
['deposit', Type.String()],
|
|
9
|
+
['status', Type.String()],
|
|
10
|
+
] as const;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { StaticDecode } from "@sinclair/typebox";
|
|
2
|
+
import {
|
|
3
|
+
type ConfigSyncProtocolType,
|
|
4
|
+
type FlattenSyncProtocolIOFor,
|
|
5
|
+
type ProtocolPrimitiveMap,
|
|
6
|
+
} from "@effectstream/config";
|
|
7
|
+
import {
|
|
8
|
+
type AddressAndType,
|
|
9
|
+
AddressType,
|
|
10
|
+
type EffectstreamBlockNumber,
|
|
11
|
+
} from "@effectstream/utils";
|
|
12
|
+
import { type JsonObject, Primitive } from "@effectstream/sm";
|
|
13
|
+
import {
|
|
14
|
+
type CommandTuple,
|
|
15
|
+
generateRawStmInput,
|
|
16
|
+
type ParamToData,
|
|
17
|
+
} from "@effectstream/concise";
|
|
18
|
+
import type { StateUpdateStream } from "@effectstream/coroutine";
|
|
19
|
+
import { nearAccountWatchGrammar } from "./near-account-watch-grammar.ts";
|
|
20
|
+
import { PrimitiveTypeNEARAccountWatch } from "../builtin.ts";
|
|
21
|
+
|
|
22
|
+
export class NearAccountWatchPrimitive extends Primitive<
|
|
23
|
+
ConfigSyncProtocolType.NEAR_RPC_PARALLEL,
|
|
24
|
+
typeof nearAccountWatchGrammar
|
|
25
|
+
> {
|
|
26
|
+
readonly internalTypeName = PrimitiveTypeNEARAccountWatch;
|
|
27
|
+
override grammar = nearAccountWatchGrammar;
|
|
28
|
+
readonly contractId: string;
|
|
29
|
+
|
|
30
|
+
constructor(config: {
|
|
31
|
+
instanceName: string;
|
|
32
|
+
startBlockHeight: number;
|
|
33
|
+
contractId: string;
|
|
34
|
+
stateMachinePrefix: string | undefined;
|
|
35
|
+
}) {
|
|
36
|
+
super(config);
|
|
37
|
+
this.contractId = config.contractId;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
override *getPayload(
|
|
41
|
+
_: EffectstreamBlockNumber,
|
|
42
|
+
primitiveTransactionData: FlattenSyncProtocolIOFor<
|
|
43
|
+
ConfigSyncProtocolType.NEAR_RPC_PARALLEL
|
|
44
|
+
>,
|
|
45
|
+
): StateUpdateStream<{
|
|
46
|
+
isBatched: boolean;
|
|
47
|
+
data: {
|
|
48
|
+
fromAddressAndType: AddressAndType;
|
|
49
|
+
stateMachinePayload:
|
|
50
|
+
| StaticDecode<CommandTuple<string, typeof nearAccountWatchGrammar>>
|
|
51
|
+
| null;
|
|
52
|
+
accountingPayload: JsonObject;
|
|
53
|
+
}[];
|
|
54
|
+
}> {
|
|
55
|
+
const payload = primitiveTransactionData.output.payload as Record<string, unknown>;
|
|
56
|
+
const signerId = String(payload.signer_id ?? "");
|
|
57
|
+
const receiverId = String(payload.receiver_id ?? "");
|
|
58
|
+
const methodName = String(payload.method_name ?? "");
|
|
59
|
+
const args = String(payload.args ?? "");
|
|
60
|
+
const deposit = String(payload.deposit ?? "0");
|
|
61
|
+
const status = String(payload.status ?? "unknown");
|
|
62
|
+
|
|
63
|
+
const accountingPayload: ParamToData<typeof nearAccountWatchGrammar> = {
|
|
64
|
+
signer_id: signerId,
|
|
65
|
+
receiver_id: receiverId,
|
|
66
|
+
method_name: methodName,
|
|
67
|
+
args,
|
|
68
|
+
deposit,
|
|
69
|
+
status,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const stateMachinePayload = this.stateMachinePrefix
|
|
73
|
+
? generateRawStmInput(
|
|
74
|
+
this.grammar,
|
|
75
|
+
this.stateMachinePrefix,
|
|
76
|
+
accountingPayload,
|
|
77
|
+
)
|
|
78
|
+
: null;
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
isBatched: false,
|
|
82
|
+
data: [
|
|
83
|
+
{
|
|
84
|
+
fromAddressAndType: {
|
|
85
|
+
type: AddressType.NEAR,
|
|
86
|
+
address: signerId,
|
|
87
|
+
},
|
|
88
|
+
accountingPayload,
|
|
89
|
+
stateMachinePayload,
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
override getConfig(): ProtocolPrimitiveMap[
|
|
96
|
+
ConfigSyncProtocolType.NEAR_RPC_PARALLEL
|
|
97
|
+
] {
|
|
98
|
+
return {
|
|
99
|
+
name: this.instanceName,
|
|
100
|
+
type: this.internalTypeName,
|
|
101
|
+
startBlockHeight: this.startBlockHeight,
|
|
102
|
+
contractId: this.contractId,
|
|
103
|
+
scheduledPrefix: this.stateMachinePrefix,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { StaticDecode } from "@sinclair/typebox";
|
|
2
|
+
import {
|
|
3
|
+
type ConfigSyncProtocolType,
|
|
4
|
+
type FlattenSyncProtocolIOFor,
|
|
5
|
+
type ProtocolPrimitiveMap,
|
|
6
|
+
} from "@effectstream/config";
|
|
7
|
+
import {
|
|
8
|
+
type AddressAndType,
|
|
9
|
+
AddressType,
|
|
10
|
+
type EffectstreamBlockNumber,
|
|
11
|
+
} from "@effectstream/utils";
|
|
12
|
+
import { type JsonObject, Primitive } from "@effectstream/sm";
|
|
13
|
+
import {
|
|
14
|
+
type CommandTuple,
|
|
15
|
+
generateRawStmInput,
|
|
16
|
+
type ParamToData,
|
|
17
|
+
} from "@effectstream/concise";
|
|
18
|
+
import type { StateUpdateStream } from "@effectstream/coroutine";
|
|
19
|
+
import { nearGenericGrammar } from "./near-generic-grammar.ts";
|
|
20
|
+
import { PrimitiveTypeNEARGeneric } from "../builtin.ts";
|
|
21
|
+
|
|
22
|
+
export class NearGenericPrimitive extends Primitive<
|
|
23
|
+
ConfigSyncProtocolType.NEAR_RPC_PARALLEL,
|
|
24
|
+
typeof nearGenericGrammar
|
|
25
|
+
> {
|
|
26
|
+
readonly internalTypeName = PrimitiveTypeNEARGeneric;
|
|
27
|
+
override grammar = nearGenericGrammar;
|
|
28
|
+
readonly contractId: string;
|
|
29
|
+
readonly eventStandard: string;
|
|
30
|
+
readonly eventType: string;
|
|
31
|
+
|
|
32
|
+
constructor(config: {
|
|
33
|
+
instanceName: string;
|
|
34
|
+
startBlockHeight: number;
|
|
35
|
+
contractId: string;
|
|
36
|
+
eventStandard: string;
|
|
37
|
+
eventType: string;
|
|
38
|
+
stateMachinePrefix: string | undefined;
|
|
39
|
+
}) {
|
|
40
|
+
super(config);
|
|
41
|
+
this.contractId = config.contractId;
|
|
42
|
+
this.eventStandard = config.eventStandard;
|
|
43
|
+
this.eventType = config.eventType;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
override *getPayload(
|
|
47
|
+
_: EffectstreamBlockNumber,
|
|
48
|
+
primitiveTransactionData: FlattenSyncProtocolIOFor<
|
|
49
|
+
ConfigSyncProtocolType.NEAR_RPC_PARALLEL
|
|
50
|
+
>,
|
|
51
|
+
): StateUpdateStream<{
|
|
52
|
+
isBatched: boolean;
|
|
53
|
+
data: {
|
|
54
|
+
fromAddressAndType: AddressAndType;
|
|
55
|
+
stateMachinePayload:
|
|
56
|
+
| StaticDecode<CommandTuple<string, typeof nearGenericGrammar>>
|
|
57
|
+
| null;
|
|
58
|
+
accountingPayload: JsonObject;
|
|
59
|
+
}[];
|
|
60
|
+
}> {
|
|
61
|
+
const payload = primitiveTransactionData.output.payload;
|
|
62
|
+
|
|
63
|
+
const accountingPayload: ParamToData<typeof nearGenericGrammar> = {
|
|
64
|
+
payload,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const stateMachinePayload = this.stateMachinePrefix
|
|
68
|
+
? generateRawStmInput(
|
|
69
|
+
this.grammar,
|
|
70
|
+
this.stateMachinePrefix,
|
|
71
|
+
accountingPayload,
|
|
72
|
+
)
|
|
73
|
+
: null;
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
isBatched: false,
|
|
77
|
+
data: [
|
|
78
|
+
{
|
|
79
|
+
fromAddressAndType: {
|
|
80
|
+
type: AddressType.NEAR,
|
|
81
|
+
address: String(
|
|
82
|
+
primitiveTransactionData.syncProtocol.contractAddress ?? "",
|
|
83
|
+
),
|
|
84
|
+
},
|
|
85
|
+
accountingPayload,
|
|
86
|
+
stateMachinePayload,
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
override getConfig(): ProtocolPrimitiveMap[
|
|
93
|
+
ConfigSyncProtocolType.NEAR_RPC_PARALLEL
|
|
94
|
+
] {
|
|
95
|
+
return {
|
|
96
|
+
name: this.instanceName,
|
|
97
|
+
type: this.internalTypeName,
|
|
98
|
+
startBlockHeight: this.startBlockHeight,
|
|
99
|
+
contractId: this.contractId,
|
|
100
|
+
eventStandard: this.eventStandard,
|
|
101
|
+
eventType: this.eventType,
|
|
102
|
+
scheduledPrefix: this.stateMachinePrefix,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
|
|
3
|
+
export const nearIntentGrammar = [
|
|
4
|
+
['account_id', Type.String()],
|
|
5
|
+
['intent_hash', Type.String()],
|
|
6
|
+
['token_diffs', Type.Array(Type.Object({
|
|
7
|
+
token_id: Type.String(),
|
|
8
|
+
amount: Type.String(),
|
|
9
|
+
}))],
|
|
10
|
+
] as const;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { PrimitiveTypeNEARIntent } from "../builtin.ts";
|
|
2
|
+
|
|
3
|
+
export function nearIntentIvm(name: string) {
|
|
4
|
+
const lowerName = name.toLowerCase();
|
|
5
|
+
const validSQLName = lowerName.replace(/[^a-zA-Z0-9_]/g, "");
|
|
6
|
+
if (validSQLName !== lowerName) {
|
|
7
|
+
throw new Error(`Invalid name: ${name}`);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const settlementTable = `primitives.near_intent_settlement_intermediate_${validSQLName}`;
|
|
11
|
+
|
|
12
|
+
return `
|
|
13
|
+
CREATE TABLE IF NOT EXISTS ${settlementTable} (
|
|
14
|
+
primitive_name TEXT NOT NULL,
|
|
15
|
+
intent_hash TEXT NOT NULL,
|
|
16
|
+
account_id TEXT NOT NULL,
|
|
17
|
+
token_id TEXT NOT NULL,
|
|
18
|
+
amount numeric(78,0) DEFAULT 0,
|
|
19
|
+
block_height INTEGER NOT NULL DEFAULT 0,
|
|
20
|
+
PRIMARY KEY (primitive_name, intent_hash, account_id, token_id)
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
CREATE OR REPLACE FUNCTION update_near_intent_settlement_${validSQLName}() RETURNS TRIGGER AS $$
|
|
24
|
+
DECLARE
|
|
25
|
+
diff_item JSONB;
|
|
26
|
+
BEGIN
|
|
27
|
+
IF NEW.payload_type = '${PrimitiveTypeNEARIntent}'
|
|
28
|
+
AND NEW.primitive_name = '${name}'
|
|
29
|
+
AND (NEW.payload::jsonb)->'token_diffs' IS NOT NULL THEN
|
|
30
|
+
|
|
31
|
+
FOR diff_item IN SELECT * FROM jsonb_array_elements((NEW.payload::jsonb)->'token_diffs')
|
|
32
|
+
LOOP
|
|
33
|
+
INSERT INTO ${settlementTable} (primitive_name, intent_hash, account_id, token_id, amount, block_height)
|
|
34
|
+
VALUES (
|
|
35
|
+
NEW.primitive_name,
|
|
36
|
+
(NEW.payload::jsonb)->>'intent_hash',
|
|
37
|
+
(NEW.payload::jsonb)->>'account_id',
|
|
38
|
+
diff_item->>'token_id',
|
|
39
|
+
(diff_item->>'amount')::numeric(78,0),
|
|
40
|
+
NEW.effectstream_block_height
|
|
41
|
+
)
|
|
42
|
+
ON CONFLICT (primitive_name, intent_hash, account_id, token_id) DO UPDATE SET
|
|
43
|
+
amount = (diff_item->>'amount')::numeric(78,0),
|
|
44
|
+
block_height = NEW.effectstream_block_height;
|
|
45
|
+
END LOOP;
|
|
46
|
+
END IF;
|
|
47
|
+
|
|
48
|
+
RETURN NEW;
|
|
49
|
+
END;
|
|
50
|
+
$$ LANGUAGE plpgsql;
|
|
51
|
+
|
|
52
|
+
CREATE TRIGGER trigger_update_near_intent_settlement_${validSQLName}
|
|
53
|
+
AFTER INSERT ON effectstream.primitive_accounting
|
|
54
|
+
FOR EACH ROW
|
|
55
|
+
EXECUTE FUNCTION update_near_intent_settlement_${validSQLName}();
|
|
56
|
+
|
|
57
|
+
SELECT pgivm.create_immv('primitives.near_intent_settlement_view_${validSQLName}',
|
|
58
|
+
'SELECT
|
|
59
|
+
primitive_name,
|
|
60
|
+
intent_hash,
|
|
61
|
+
account_id,
|
|
62
|
+
token_id,
|
|
63
|
+
amount,
|
|
64
|
+
block_height
|
|
65
|
+
FROM ${settlementTable};
|
|
66
|
+
');
|
|
67
|
+
`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const NEAR_INTENT_VIEW_PREFIX = "near_intent_settlement_view_" as const;
|
|
71
|
+
export const NEAR_INTENT_INTERMEDIATE_PREFIX = "near_intent_settlement_intermediate_" as const;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import type { StaticDecode } from "@sinclair/typebox";
|
|
2
|
+
import {
|
|
3
|
+
type ConfigSyncProtocolType,
|
|
4
|
+
type FlattenSyncProtocolIOFor,
|
|
5
|
+
type ProtocolPrimitiveMap,
|
|
6
|
+
} from "@effectstream/config";
|
|
7
|
+
import {
|
|
8
|
+
type AddressAndType,
|
|
9
|
+
AddressType,
|
|
10
|
+
type EffectstreamBlockNumber,
|
|
11
|
+
} from "@effectstream/utils";
|
|
12
|
+
import { type JsonObject, Primitive } from "@effectstream/sm";
|
|
13
|
+
import {
|
|
14
|
+
type CommandTuple,
|
|
15
|
+
generateRawStmInput,
|
|
16
|
+
type ParamToData,
|
|
17
|
+
} from "@effectstream/concise";
|
|
18
|
+
import type { StateUpdateStream } from "@effectstream/coroutine";
|
|
19
|
+
import { nearIntentGrammar } from "./near-intent-grammar.ts";
|
|
20
|
+
import {
|
|
21
|
+
NEAR_INTENT_INTERMEDIATE_PREFIX,
|
|
22
|
+
NEAR_INTENT_VIEW_PREFIX,
|
|
23
|
+
nearIntentIvm,
|
|
24
|
+
} from "./near-intent-ivm.ts";
|
|
25
|
+
import { PrimitiveTypeNEARIntent } from "../builtin.ts";
|
|
26
|
+
import { matchesGlob } from "./near-intent-token-id-parser.ts";
|
|
27
|
+
|
|
28
|
+
export class NearIntentPrimitive extends Primitive<
|
|
29
|
+
ConfigSyncProtocolType.NEAR_RPC_PARALLEL,
|
|
30
|
+
typeof nearIntentGrammar
|
|
31
|
+
> {
|
|
32
|
+
readonly internalTypeName = PrimitiveTypeNEARIntent;
|
|
33
|
+
override grammar = nearIntentGrammar;
|
|
34
|
+
readonly contractId: string;
|
|
35
|
+
readonly filterTokenIds: string[];
|
|
36
|
+
readonly filterAccountIds: string[];
|
|
37
|
+
|
|
38
|
+
override dynamicTables = nearIntentIvm;
|
|
39
|
+
override getIntermediatePrefix(): string[] {
|
|
40
|
+
return [NEAR_INTENT_INTERMEDIATE_PREFIX];
|
|
41
|
+
}
|
|
42
|
+
override getViewPrefix(): string[] {
|
|
43
|
+
return [NEAR_INTENT_VIEW_PREFIX];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
constructor(config: {
|
|
47
|
+
instanceName: string;
|
|
48
|
+
startBlockHeight: number;
|
|
49
|
+
contractId: string;
|
|
50
|
+
stateMachinePrefix: string | undefined;
|
|
51
|
+
filterTokenIds?: string[];
|
|
52
|
+
filterAccountIds?: string[];
|
|
53
|
+
}) {
|
|
54
|
+
super(config);
|
|
55
|
+
this.contractId = config.contractId;
|
|
56
|
+
this.filterTokenIds = config.filterTokenIds ?? [];
|
|
57
|
+
this.filterAccountIds = config.filterAccountIds ?? [];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
override *getPayload(
|
|
61
|
+
_: EffectstreamBlockNumber,
|
|
62
|
+
primitiveTransactionData: FlattenSyncProtocolIOFor<
|
|
63
|
+
ConfigSyncProtocolType.NEAR_RPC_PARALLEL
|
|
64
|
+
>,
|
|
65
|
+
): StateUpdateStream<{
|
|
66
|
+
isBatched: boolean;
|
|
67
|
+
data: {
|
|
68
|
+
fromAddressAndType: AddressAndType;
|
|
69
|
+
stateMachinePayload:
|
|
70
|
+
| StaticDecode<CommandTuple<string, typeof nearIntentGrammar>>
|
|
71
|
+
| null;
|
|
72
|
+
accountingPayload: JsonObject;
|
|
73
|
+
}[];
|
|
74
|
+
}> {
|
|
75
|
+
const payload = primitiveTransactionData.output.payload as Record<string, unknown>;
|
|
76
|
+
const accountId = String(payload.account_id ?? "");
|
|
77
|
+
const intentHash = String(payload.intent_hash ?? "");
|
|
78
|
+
|
|
79
|
+
// Apply account filter
|
|
80
|
+
if (
|
|
81
|
+
this.filterAccountIds.length > 0 &&
|
|
82
|
+
!this.filterAccountIds.some((p) => matchesGlob(p, accountId))
|
|
83
|
+
) {
|
|
84
|
+
return { isBatched: false, data: [] };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Parse DIP-4 diff object into token_diffs array
|
|
88
|
+
const diff = (payload.diff ?? {}) as Record<string, string>;
|
|
89
|
+
const tokenDiffs: { token_id: string; amount: string }[] = [];
|
|
90
|
+
for (const [tokenId, amount] of Object.entries(diff)) {
|
|
91
|
+
// Apply token filter
|
|
92
|
+
if (
|
|
93
|
+
this.filterTokenIds.length > 0 &&
|
|
94
|
+
!this.filterTokenIds.some((p) => matchesGlob(p, tokenId))
|
|
95
|
+
) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
tokenDiffs.push({ token_id: tokenId, amount: String(amount) });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (tokenDiffs.length === 0) {
|
|
102
|
+
return { isBatched: false, data: [] };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const accountingPayload: ParamToData<typeof nearIntentGrammar> = {
|
|
106
|
+
account_id: accountId,
|
|
107
|
+
intent_hash: intentHash,
|
|
108
|
+
token_diffs: tokenDiffs,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const stateMachinePayload = this.stateMachinePrefix
|
|
112
|
+
? generateRawStmInput(
|
|
113
|
+
this.grammar,
|
|
114
|
+
this.stateMachinePrefix,
|
|
115
|
+
accountingPayload,
|
|
116
|
+
)
|
|
117
|
+
: null;
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
isBatched: false,
|
|
121
|
+
data: [
|
|
122
|
+
{
|
|
123
|
+
fromAddressAndType: {
|
|
124
|
+
type: AddressType.NEAR,
|
|
125
|
+
address: accountId,
|
|
126
|
+
},
|
|
127
|
+
accountingPayload,
|
|
128
|
+
stateMachinePayload,
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
override getConfig(): ProtocolPrimitiveMap[
|
|
135
|
+
ConfigSyncProtocolType.NEAR_RPC_PARALLEL
|
|
136
|
+
] {
|
|
137
|
+
return {
|
|
138
|
+
name: this.instanceName,
|
|
139
|
+
type: this.internalTypeName,
|
|
140
|
+
startBlockHeight: this.startBlockHeight,
|
|
141
|
+
contractId: this.contractId,
|
|
142
|
+
eventStandard: "dip4",
|
|
143
|
+
eventType: "token_diff",
|
|
144
|
+
filterTokenIds: this.filterTokenIds,
|
|
145
|
+
filterAccountIds: this.filterAccountIds,
|
|
146
|
+
scheduledPrefix: this.stateMachinePrefix,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses a NEAR Intents Verifier namespaced token ID.
|
|
3
|
+
*
|
|
4
|
+
* Token IDs follow the format: `standard:contract[:localId]`
|
|
5
|
+
* Examples:
|
|
6
|
+
* "nep141:wrap.near" → { standard: "nep141", contract: "wrap.near", localId: null }
|
|
7
|
+
* "nep171:nft.near:token42" → { standard: "nep171", contract: "nft.near", localId: "token42" }
|
|
8
|
+
* "nep245:game.near:sword" → { standard: "nep245", contract: "game.near", localId: "sword" }
|
|
9
|
+
*/
|
|
10
|
+
export type ParsedTokenId = {
|
|
11
|
+
standard: string;
|
|
12
|
+
contract: string;
|
|
13
|
+
localId: string | null;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function parseIntentTokenId(tokenId: string): ParsedTokenId {
|
|
17
|
+
const firstColon = tokenId.indexOf(":");
|
|
18
|
+
if (firstColon === -1) {
|
|
19
|
+
return { standard: "unknown", contract: tokenId, localId: null };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const standard = tokenId.slice(0, firstColon);
|
|
23
|
+
const rest = tokenId.slice(firstColon + 1);
|
|
24
|
+
|
|
25
|
+
const secondColon = rest.indexOf(":");
|
|
26
|
+
if (secondColon === -1) {
|
|
27
|
+
return { standard, contract: rest, localId: null };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
standard,
|
|
32
|
+
contract: rest.slice(0, secondColon),
|
|
33
|
+
localId: rest.slice(secondColon + 1),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Simple glob matcher supporting `*` (matches any characters except `.`)
|
|
39
|
+
* and `**` or trailing `*` (matches everything).
|
|
40
|
+
*/
|
|
41
|
+
export function matchesGlob(pattern: string, value: string): boolean {
|
|
42
|
+
const regex = pattern
|
|
43
|
+
.replace(/[.+^${}()|[\]\\]/g, "\\$&")
|
|
44
|
+
.replace(/\*\*/g, ".*")
|
|
45
|
+
.replace(/\*/g, "[^.]*");
|
|
46
|
+
return new RegExp(`^${regex}$`).test(value);
|
|
47
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { PrimitiveTypeNEARNEP141 } from "../builtin.ts";
|
|
2
|
+
|
|
3
|
+
export function nep141Ivm(name: string) {
|
|
4
|
+
const lowerName = name.toLowerCase();
|
|
5
|
+
const validSQLName = lowerName.replace(/[^a-zA-Z0-9_]/g, "");
|
|
6
|
+
if (validSQLName !== lowerName) {
|
|
7
|
+
throw new Error(`Invalid name: ${name}`);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const balanceTable = `primitives.nep141_balance_intermediate_${validSQLName}`;
|
|
11
|
+
|
|
12
|
+
return `
|
|
13
|
+
CREATE TABLE IF NOT EXISTS ${balanceTable} (
|
|
14
|
+
primitive_name TEXT NOT NULL,
|
|
15
|
+
account_id TEXT NOT NULL,
|
|
16
|
+
balance numeric(78,0) DEFAULT 0,
|
|
17
|
+
PRIMARY KEY (primitive_name, account_id)
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
CREATE OR REPLACE FUNCTION update_nep141_balance_${validSQLName}() RETURNS TRIGGER AS $$
|
|
21
|
+
DECLARE
|
|
22
|
+
transfer_amount numeric(78,0);
|
|
23
|
+
from_account TEXT;
|
|
24
|
+
to_account TEXT;
|
|
25
|
+
BEGIN
|
|
26
|
+
IF NEW.payload_type = '${PrimitiveTypeNEARNEP141}'
|
|
27
|
+
AND NEW.primitive_name = '${name}'
|
|
28
|
+
AND NEW.payload->>'amount' IS NOT NULL THEN
|
|
29
|
+
|
|
30
|
+
transfer_amount := (NEW.payload->>'amount')::numeric(78,0);
|
|
31
|
+
from_account := NEW.payload->>'old_owner_id';
|
|
32
|
+
to_account := NEW.payload->>'new_owner_id';
|
|
33
|
+
|
|
34
|
+
IF from_account IS NOT NULL AND from_account != '' THEN
|
|
35
|
+
INSERT INTO ${balanceTable} (primitive_name, account_id, balance)
|
|
36
|
+
VALUES (NEW.primitive_name, from_account, -transfer_amount)
|
|
37
|
+
ON CONFLICT (primitive_name, account_id) DO UPDATE SET
|
|
38
|
+
balance = ${balanceTable}.balance - transfer_amount;
|
|
39
|
+
END IF;
|
|
40
|
+
|
|
41
|
+
IF to_account IS NOT NULL AND to_account != '' THEN
|
|
42
|
+
INSERT INTO ${balanceTable} (primitive_name, account_id, balance)
|
|
43
|
+
VALUES (NEW.primitive_name, to_account, transfer_amount)
|
|
44
|
+
ON CONFLICT (primitive_name, account_id) DO UPDATE SET
|
|
45
|
+
balance = ${balanceTable}.balance + transfer_amount;
|
|
46
|
+
END IF;
|
|
47
|
+
END IF;
|
|
48
|
+
|
|
49
|
+
RETURN NEW;
|
|
50
|
+
END;
|
|
51
|
+
$$ LANGUAGE plpgsql;
|
|
52
|
+
|
|
53
|
+
CREATE TRIGGER trigger_update_nep141_balance_${validSQLName}
|
|
54
|
+
AFTER INSERT ON effectstream.primitive_accounting
|
|
55
|
+
FOR EACH ROW
|
|
56
|
+
EXECUTE FUNCTION update_nep141_balance_${validSQLName}();
|
|
57
|
+
|
|
58
|
+
SELECT pgivm.create_immv('primitives.nep141_balance_view_${validSQLName}',
|
|
59
|
+
'SELECT
|
|
60
|
+
primitive_name,
|
|
61
|
+
account_id,
|
|
62
|
+
balance
|
|
63
|
+
FROM ${balanceTable}
|
|
64
|
+
WHERE balance > 0;
|
|
65
|
+
');
|
|
66
|
+
`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const NEP141_VIEW_PREFIX = "nep141_balance_view_" as const;
|
|
70
|
+
export const NEP141_INTERMEDIATE_PREFIX = "nep141_balance_intermediate_" as const;
|