@effectstream/sm 0.100.12 → 0.100.14
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/package.json +9 -8
- package/primitives/src/builtin.ts +12 -0
- package/primitives/src/cardano-delayed-asset/delayed-asset-grammar.ts +11 -0
- package/primitives/src/cardano-delayed-asset/delayed-asset-ivm.ts +89 -0
- package/primitives/src/cardano-delayed-asset/delayed-asset-primitive.ts +228 -0
- package/primitives/src/cardano-mint-burn/mint-burn-grammar.ts +9 -0
- package/primitives/src/cardano-mint-burn/mint-burn-primitive.ts +160 -0
- package/primitives/src/cardano-pool-delegation/pool-delegation-grammar.ts +7 -0
- package/primitives/src/cardano-pool-delegation/pool-delegation-ivm.ts +65 -0
- package/primitives/src/cardano-pool-delegation/pool-delegation-primitive.ts +150 -0
- package/primitives/src/cardano-projected-nft/projected-nft-datum.ts +107 -0
- package/primitives/src/cardano-projected-nft/projected-nft-grammar.ts +13 -0
- package/primitives/src/cardano-projected-nft/projected-nft-ivm.ts +108 -0
- package/primitives/src/cardano-projected-nft/projected-nft-primitive.ts +242 -0
- package/primitives/src/cardano-transfer/transfer-grammar.ts +8 -0
- package/primitives/src/cardano-transfer/transfer-primitive.ts +150 -0
- package/primitives/src/cardano-utils/cardano-helpers.ts +84 -0
- package/primitives/src/grammar.ts +10 -0
- package/primitives/src/midnight-generic/midnight-genetic.ts +15 -0
- package/primitives/src/midnight-unshielded-spend/midnight-unshielded-spend-grammar.ts +8 -0
- package/primitives/src/midnight-unshielded-spend/midnight-unshielded-spend.ts +115 -0
- package/primitives/src/mod.ts +24 -0
- package/types.ts +27 -5
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cardano Transfer Primitive
|
|
3
|
+
*
|
|
4
|
+
* Captures ADA and native asset transfers from Dolos UTxORPC block data.
|
|
5
|
+
*
|
|
6
|
+
* Data source: Dolos streams raw Cardano blocks via gRPC. Each transaction contains
|
|
7
|
+
* `outputs` (destination UTxOs with address, lovelace coin, and native assets) and
|
|
8
|
+
* `witnesses.vkeywitness` (verification key witnesses proving input authorization).
|
|
9
|
+
*
|
|
10
|
+
* Extraction: for each matched transaction, `getPayload()` maps `tx.outputs` into
|
|
11
|
+
* structured objects with `{index, address, coin, assets[]}`. Coin values are extracted
|
|
12
|
+
* from the protobuf BigInt (either `int` for small values or `bigUInt` for large).
|
|
13
|
+
* Input credentials are extracted from `tx.witnesses.vkeywitness[].vkey` — these are
|
|
14
|
+
* the public key hashes that signed the transaction, identifying who authorized the spend.
|
|
15
|
+
* Transaction metadata is extracted from `tx.auxiliary.metadata`.
|
|
16
|
+
*
|
|
17
|
+
* Predicate: user-provided (typically `has_address` to watch specific addresses).
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import type { StaticDecode } from "@sinclair/typebox";
|
|
21
|
+
import {
|
|
22
|
+
type CommandTuple,
|
|
23
|
+
generateRawStmInput,
|
|
24
|
+
} from "@effectstream/concise";
|
|
25
|
+
import type {
|
|
26
|
+
ConfigSyncProtocolType,
|
|
27
|
+
FlattenSyncProtocolIOFor,
|
|
28
|
+
ProtocolPrimitiveMap,
|
|
29
|
+
UtxorpcTxPredicate,
|
|
30
|
+
} from "@effectstream/config";
|
|
31
|
+
import type { StateUpdateStream } from "@effectstream/coroutine";
|
|
32
|
+
import { type JsonObject, Primitive } from "@effectstream/sm";
|
|
33
|
+
import {
|
|
34
|
+
type AddressAndType,
|
|
35
|
+
AddressType,
|
|
36
|
+
type EffectstreamBlockNumber,
|
|
37
|
+
uint8ArrayToHexString,
|
|
38
|
+
} from "@effectstream/utils";
|
|
39
|
+
import { transferGrammar } from "./transfer-grammar.ts";
|
|
40
|
+
import { PrimitiveTypeCardanoTransfer } from "../builtin.ts";
|
|
41
|
+
import {
|
|
42
|
+
addressToHex,
|
|
43
|
+
assetQuantityToString,
|
|
44
|
+
metadataToJson,
|
|
45
|
+
} from "../cardano-utils/cardano-helpers.ts";
|
|
46
|
+
|
|
47
|
+
export class CardanoTransferPrimitive extends Primitive<
|
|
48
|
+
ConfigSyncProtocolType.CARDANO_UTXORPC_PARALLEL,
|
|
49
|
+
typeof transferGrammar
|
|
50
|
+
> {
|
|
51
|
+
readonly internalTypeName = PrimitiveTypeCardanoTransfer;
|
|
52
|
+
readonly predicate: UtxorpcTxPredicate;
|
|
53
|
+
override grammar = transferGrammar;
|
|
54
|
+
|
|
55
|
+
constructor(config: {
|
|
56
|
+
instanceName: string;
|
|
57
|
+
startBlockHeight: number;
|
|
58
|
+
stateMachinePrefix: string | undefined;
|
|
59
|
+
predicate: UtxorpcTxPredicate;
|
|
60
|
+
}) {
|
|
61
|
+
super(config);
|
|
62
|
+
this.predicate = config.predicate;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
override getConfig(): ProtocolPrimitiveMap[ConfigSyncProtocolType.CARDANO_UTXORPC_PARALLEL] {
|
|
66
|
+
return {
|
|
67
|
+
name: this.instanceName,
|
|
68
|
+
type: this.internalTypeName,
|
|
69
|
+
startBlockHeight: this.startBlockHeight,
|
|
70
|
+
scheduledPrefix: this.stateMachinePrefix,
|
|
71
|
+
predicate: this.predicate,
|
|
72
|
+
} as const;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
override *getPayload(
|
|
76
|
+
_: EffectstreamBlockNumber,
|
|
77
|
+
primitiveTransactionData: FlattenSyncProtocolIOFor<ConfigSyncProtocolType.CARDANO_UTXORPC_PARALLEL>,
|
|
78
|
+
): StateUpdateStream<{
|
|
79
|
+
isBatched: boolean;
|
|
80
|
+
data: {
|
|
81
|
+
fromAddressAndType: AddressAndType;
|
|
82
|
+
stateMachinePayload: StaticDecode<CommandTuple<string, typeof transferGrammar>> | null;
|
|
83
|
+
accountingPayload: JsonObject;
|
|
84
|
+
}[];
|
|
85
|
+
}> {
|
|
86
|
+
const tx = primitiveTransactionData.output.payload.tx;
|
|
87
|
+
|
|
88
|
+
const txId = uint8ArrayToHexString(tx.hash);
|
|
89
|
+
|
|
90
|
+
const outputs = tx.outputs.map((out, index) => {
|
|
91
|
+
const address = addressToHex(out.address);
|
|
92
|
+
const coin = out.coin?.bigInt.case === "int"
|
|
93
|
+
? String(out.coin.bigInt.value)
|
|
94
|
+
: out.coin?.bigInt.case === "bigUInt"
|
|
95
|
+
? uint8ArrayToHexString(out.coin.bigInt.value)
|
|
96
|
+
: "0";
|
|
97
|
+
|
|
98
|
+
const assets: { policyId: string; assetName: string; amount: string }[] = [];
|
|
99
|
+
for (const ma of out.assets) {
|
|
100
|
+
const policyId = uint8ArrayToHexString(ma.policyId);
|
|
101
|
+
for (const asset of ma.assets) {
|
|
102
|
+
assets.push({
|
|
103
|
+
policyId,
|
|
104
|
+
assetName: uint8ArrayToHexString(asset.name),
|
|
105
|
+
amount: assetQuantityToString(asset),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return { index, address, coin, assets };
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const inputCredentials: string[] = [];
|
|
114
|
+
if (tx.witnesses) {
|
|
115
|
+
for (const w of tx.witnesses.vkeywitness) {
|
|
116
|
+
const hash = uint8ArrayToHexString(w.vkey);
|
|
117
|
+
if (!inputCredentials.includes(hash)) inputCredentials.push(hash);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const metadata = metadataToJson(tx.auxiliary?.metadata ?? []);
|
|
122
|
+
|
|
123
|
+
const accountingPayload = {
|
|
124
|
+
txId,
|
|
125
|
+
metadata: metadata ? JSON.stringify(metadata) : null,
|
|
126
|
+
inputCredentials,
|
|
127
|
+
outputs,
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const stateMachinePayload: any = this.stateMachinePrefix
|
|
131
|
+
? generateRawStmInput(this.grammar, this.stateMachinePrefix, {
|
|
132
|
+
txId,
|
|
133
|
+
metadata: metadata ? JSON.stringify(metadata) : "",
|
|
134
|
+
inputCredentials: JSON.stringify(inputCredentials),
|
|
135
|
+
outputs: JSON.stringify(outputs),
|
|
136
|
+
})
|
|
137
|
+
: null;
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
isBatched: false,
|
|
141
|
+
data: [
|
|
142
|
+
{
|
|
143
|
+
fromAddressAndType: { type: AddressType.NONE, address: "0x0" },
|
|
144
|
+
accountingPayload,
|
|
145
|
+
stateMachinePayload,
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { uint8ArrayToHexString } from "@effectstream/utils";
|
|
2
|
+
import type { cardano } from "@utxorpc/spec";
|
|
3
|
+
|
|
4
|
+
type CardanoNetwork = "preview" | "preprod" | "mainnet" | "yaci";
|
|
5
|
+
|
|
6
|
+
const epochParams: Record<CardanoNetwork, { firstSlot: number; slotsPerEpoch: number; firstEpoch: number }> = {
|
|
7
|
+
mainnet: { firstSlot: 4_492_800, slotsPerEpoch: 432_000, firstEpoch: 208 },
|
|
8
|
+
preprod: { firstSlot: 86_400, slotsPerEpoch: 432_000, firstEpoch: 4 },
|
|
9
|
+
preview: { firstSlot: 0, slotsPerEpoch: 86_400, firstEpoch: 0 },
|
|
10
|
+
yaci: { firstSlot: 0, slotsPerEpoch: 600, firstEpoch: 0 },
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function slotToEpoch(slot: number, network: CardanoNetwork): number {
|
|
14
|
+
const params = epochParams[network];
|
|
15
|
+
if (slot < params.firstSlot) return 0;
|
|
16
|
+
return params.firstEpoch + Math.floor((slot - params.firstSlot) / params.slotsPerEpoch);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function stakeCredentialToHex(cred: cardano.StakeCredential): { type: "key" | "script"; hash: string } | null {
|
|
20
|
+
const inner = cred.stakeCredential;
|
|
21
|
+
if (inner.case === "addrKeyHash") {
|
|
22
|
+
return { type: "key", hash: uint8ArrayToHexString(inner.value) };
|
|
23
|
+
}
|
|
24
|
+
if (inner.case === "scriptHash") {
|
|
25
|
+
return { type: "script", hash: uint8ArrayToHexString(inner.value) };
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function addressToHex(address: Uint8Array): string {
|
|
31
|
+
return uint8ArrayToHexString(address);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function metadataToJson(metadata: cardano.Metadata[]): Record<string, unknown> | null {
|
|
35
|
+
if (!metadata || metadata.length === 0) return null;
|
|
36
|
+
const result: Record<string, unknown> = {};
|
|
37
|
+
for (const entry of metadata) {
|
|
38
|
+
result[String(entry.label)] = entry.value ? metadatumToJson(entry.value) : null;
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function metadatumToJson(m: cardano.Metadatum): unknown {
|
|
44
|
+
const inner = m.metadatum;
|
|
45
|
+
if (!inner || inner.case === undefined) return null;
|
|
46
|
+
switch (inner.case) {
|
|
47
|
+
case "int": return String(inner.value);
|
|
48
|
+
case "bytes": return uint8ArrayToHexString(inner.value);
|
|
49
|
+
case "text": return inner.value;
|
|
50
|
+
case "array": return inner.value.items.map(metadatumToJson);
|
|
51
|
+
case "map": return inner.value.pairs.map(p => ({
|
|
52
|
+
k: p.key ? metadatumToJson(p.key) : null,
|
|
53
|
+
v: p.value ? metadatumToJson(p.value) : null,
|
|
54
|
+
}));
|
|
55
|
+
default: return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function bigIntToString(bi: cardano.BigInt): string {
|
|
60
|
+
const inner = bi.bigInt;
|
|
61
|
+
if (inner.case === "int") return String(inner.value);
|
|
62
|
+
if (inner.case === "bigUInt") {
|
|
63
|
+
let result = 0n;
|
|
64
|
+
for (const byte of inner.value) result = (result << 8n) | BigInt(byte);
|
|
65
|
+
return String(result);
|
|
66
|
+
}
|
|
67
|
+
if (inner.case === "bigNInt") {
|
|
68
|
+
let result = 0n;
|
|
69
|
+
for (const byte of inner.value) result = (result << 8n) | BigInt(byte);
|
|
70
|
+
return String(-result);
|
|
71
|
+
}
|
|
72
|
+
return "0";
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function assetQuantityToString(asset: cardano.Asset): string {
|
|
76
|
+
const q = asset.quantity;
|
|
77
|
+
if (q.case === "outputCoin") return bigIntToString(q.value);
|
|
78
|
+
if (q.case === "mintCoin") return bigIntToString(q.value);
|
|
79
|
+
return "0";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function isMintQuantity(asset: cardano.Asset): boolean {
|
|
83
|
+
return asset.quantity.case === "mintCoin";
|
|
84
|
+
}
|
|
@@ -15,6 +15,11 @@ import { nep245Grammar } from "./near-nep245/nep245-grammar.ts";
|
|
|
15
15
|
import { nearIntentGrammar } from "./near-intent/near-intent-grammar.ts";
|
|
16
16
|
import { nearGenericGrammar } from "./near-generic/near-generic-grammar.ts";
|
|
17
17
|
import { nearAccountWatchGrammar } from "./near-account-watch/near-account-watch-grammar.ts";
|
|
18
|
+
import { mintBurnGrammar } from "./cardano-mint-burn/mint-burn-grammar.ts";
|
|
19
|
+
import { transferGrammar } from "./cardano-transfer/transfer-grammar.ts";
|
|
20
|
+
import { poolDelegationGrammar } from "./cardano-pool-delegation/pool-delegation-grammar.ts";
|
|
21
|
+
import { delayedAssetGrammar } from "./cardano-delayed-asset/delayed-asset-grammar.ts";
|
|
22
|
+
import { projectedNftGrammar } from "./cardano-projected-nft/projected-nft-grammar.ts";
|
|
18
23
|
|
|
19
24
|
export const builtinGrammars = {
|
|
20
25
|
midnightGeneric: midnightGenericGrammar,
|
|
@@ -31,4 +36,9 @@ export const builtinGrammars = {
|
|
|
31
36
|
nearIntent: nearIntentGrammar,
|
|
32
37
|
nearGeneric: nearGenericGrammar,
|
|
33
38
|
nearAccountWatch: nearAccountWatchGrammar,
|
|
39
|
+
cardanoMintBurn: mintBurnGrammar,
|
|
40
|
+
cardanoTransfer: transferGrammar,
|
|
41
|
+
cardanoPoolDelegation: poolDelegationGrammar,
|
|
42
|
+
cardanoDelayedAsset: delayedAssetGrammar,
|
|
43
|
+
cardanoProjectedNft: projectedNftGrammar,
|
|
34
44
|
} as const;
|
|
@@ -242,6 +242,14 @@ function parseLedgerField(sv: StateValue, type: LedgerFieldType): any {
|
|
|
242
242
|
return null;
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
+
function isCompactMap(data: object): data is Iterable<[unknown, unknown]> {
|
|
246
|
+
return (
|
|
247
|
+
typeof (data as any).member === 'function' &&
|
|
248
|
+
typeof (data as any).lookup === 'function' &&
|
|
249
|
+
Symbol.iterator in data
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
245
253
|
function makeJsonSafe(data: unknown): any {
|
|
246
254
|
if (typeof data === 'boolean' || typeof data === 'number' || typeof data === 'string') {
|
|
247
255
|
return data;
|
|
@@ -259,6 +267,13 @@ function makeJsonSafe(data: unknown): any {
|
|
|
259
267
|
return uint8ArrayToHexString(data);
|
|
260
268
|
}
|
|
261
269
|
if (typeof data === 'object') {
|
|
270
|
+
if (isCompactMap(data)) {
|
|
271
|
+
const entries: [string, any][] = [];
|
|
272
|
+
for (const [k, v] of data) {
|
|
273
|
+
entries.push([String(makeJsonSafe(k)), makeJsonSafe(v)]);
|
|
274
|
+
}
|
|
275
|
+
return Object.fromEntries(entries);
|
|
276
|
+
}
|
|
262
277
|
return Object.fromEntries(Object.entries(data).map(([k, v]) => [k, makeJsonSafe(v)]));
|
|
263
278
|
}
|
|
264
279
|
return data;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Primitive } from "@effectstream/sm";
|
|
2
|
+
import {
|
|
3
|
+
type AddressAndType,
|
|
4
|
+
AddressType,
|
|
5
|
+
type EffectstreamBlockNumber,
|
|
6
|
+
} from "@effectstream/utils";
|
|
7
|
+
import type { StaticDecode } from "@sinclair/typebox";
|
|
8
|
+
import {
|
|
9
|
+
type CommandTuple,
|
|
10
|
+
generateRawStmInput,
|
|
11
|
+
type ParamToData,
|
|
12
|
+
} from "@effectstream/concise";
|
|
13
|
+
import type {
|
|
14
|
+
ConfigSyncProtocolType,
|
|
15
|
+
FlattenSyncProtocolIOFor,
|
|
16
|
+
ProtocolPrimitiveMap,
|
|
17
|
+
} from "@effectstream/config";
|
|
18
|
+
import type { SyncStateUpdateStream } from "@effectstream/coroutine";
|
|
19
|
+
import { PrimitiveTypeMidnightUnshieldedSpend } from "../builtin.ts";
|
|
20
|
+
import { midnightUnshieldedSpendGrammar } from "./midnight-unshielded-spend-grammar.ts";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* MidnightUnshieldedSpendPrimitive
|
|
24
|
+
*
|
|
25
|
+
* Watches all unshielded UTXO spend events on the Midnight ledger. The
|
|
26
|
+
* indexer's GraphQL `transactions.unshieldedSpentOutputs` field reports the
|
|
27
|
+
* `(owner, intentHash, outputIndex)` triple for each unshielded UTXO
|
|
28
|
+
* consumed in a block. One state-machine input is emitted per spend.
|
|
29
|
+
*
|
|
30
|
+
* Usage:
|
|
31
|
+
* stm.addStateTransition("myPrefix", function* (data) {
|
|
32
|
+
* const { payload } = data.parsedInput;
|
|
33
|
+
* // payload = { owner, intentHash, outputIndex, txHash }
|
|
34
|
+
* });
|
|
35
|
+
*/
|
|
36
|
+
export class MidnightUnshieldedSpendPrimitive extends Primitive<
|
|
37
|
+
ConfigSyncProtocolType.MIDNIGHT_PARALLEL,
|
|
38
|
+
typeof midnightUnshieldedSpendGrammar
|
|
39
|
+
> {
|
|
40
|
+
readonly internalTypeName = PrimitiveTypeMidnightUnshieldedSpend;
|
|
41
|
+
override readonly grammar = midnightUnshieldedSpendGrammar;
|
|
42
|
+
|
|
43
|
+
override dynamicTables = undefined;
|
|
44
|
+
override getIntermediatePrefix(): string[] {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
override getViewPrefix(): string[] {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
constructor(config: {
|
|
52
|
+
instanceName: string;
|
|
53
|
+
startBlockHeight: number;
|
|
54
|
+
stateMachinePrefix: string;
|
|
55
|
+
}) {
|
|
56
|
+
super(config);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
override *getPayload(
|
|
60
|
+
_: EffectstreamBlockNumber,
|
|
61
|
+
primitiveTransactionData: FlattenSyncProtocolIOFor<
|
|
62
|
+
ConfigSyncProtocolType.MIDNIGHT_PARALLEL
|
|
63
|
+
>,
|
|
64
|
+
): SyncStateUpdateStream<{
|
|
65
|
+
isBatched: boolean;
|
|
66
|
+
data: {
|
|
67
|
+
fromAddressAndType: AddressAndType;
|
|
68
|
+
stateMachinePayload:
|
|
69
|
+
| StaticDecode<CommandTuple<string, typeof midnightUnshieldedSpendGrammar>>
|
|
70
|
+
| null;
|
|
71
|
+
accountingPayload: ParamToData<typeof midnightUnshieldedSpendGrammar>;
|
|
72
|
+
}[];
|
|
73
|
+
}> {
|
|
74
|
+
const payload = primitiveTransactionData.output.payload;
|
|
75
|
+
|
|
76
|
+
const accountingPayload: ParamToData<typeof this.grammar> = {
|
|
77
|
+
payload,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const stateMachinePayload:
|
|
81
|
+
| StaticDecode<CommandTuple<string, typeof this.grammar>>
|
|
82
|
+
| null = this.stateMachinePrefix
|
|
83
|
+
? generateRawStmInput(
|
|
84
|
+
this.grammar,
|
|
85
|
+
this.stateMachinePrefix,
|
|
86
|
+
accountingPayload,
|
|
87
|
+
)
|
|
88
|
+
: null;
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
isBatched: false,
|
|
92
|
+
data: [
|
|
93
|
+
{
|
|
94
|
+
fromAddressAndType: {
|
|
95
|
+
type: AddressType.NONE,
|
|
96
|
+
address: "0x0",
|
|
97
|
+
},
|
|
98
|
+
accountingPayload,
|
|
99
|
+
stateMachinePayload,
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
override getConfig(): ProtocolPrimitiveMap[
|
|
106
|
+
ConfigSyncProtocolType.MIDNIGHT_PARALLEL
|
|
107
|
+
] {
|
|
108
|
+
return {
|
|
109
|
+
name: this.instanceName,
|
|
110
|
+
type: this.internalTypeName,
|
|
111
|
+
startBlockHeight: this.startBlockHeight,
|
|
112
|
+
scheduledPrefix: this.stateMachinePrefix ?? "",
|
|
113
|
+
} as const;
|
|
114
|
+
}
|
|
115
|
+
}
|
package/primitives/src/mod.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PrimitiveTypeMidnightGeneric,
|
|
3
3
|
PrimitiveTypeMidnightNullifier,
|
|
4
|
+
PrimitiveTypeMidnightUnshieldedSpend,
|
|
4
5
|
PrimitiveTypeEVMEffectstreamL2,
|
|
5
6
|
PrimitiveTypeEVMERC721,
|
|
6
7
|
PrimitiveTypeEVMERC20,
|
|
@@ -15,11 +16,17 @@ import {
|
|
|
15
16
|
PrimitiveTypeNEARIntent,
|
|
16
17
|
PrimitiveTypeNEARGeneric,
|
|
17
18
|
PrimitiveTypeNEARAccountWatch,
|
|
19
|
+
PrimitiveTypeCardanoMintBurn,
|
|
20
|
+
PrimitiveTypeCardanoTransfer,
|
|
21
|
+
PrimitiveTypeCardanoPoolDelegation,
|
|
22
|
+
PrimitiveTypeCardanoDelayedAsset,
|
|
23
|
+
PrimitiveTypeCardanoProjectedNFT,
|
|
18
24
|
// PrimitiveTypeEVMGeneric,
|
|
19
25
|
} from "./builtin.ts";
|
|
20
26
|
|
|
21
27
|
import { MidnightGenericPrimitive } from "./midnight-generic/midnight-genetic.ts";
|
|
22
28
|
import { MidnightNullifierPrimitive } from "./midnight-nullifier/midnight-nullifier.ts";
|
|
29
|
+
import { MidnightUnshieldedSpendPrimitive } from "./midnight-unshielded-spend/midnight-unshielded-spend.ts";
|
|
23
30
|
import { EffectstreamL2Primitive } from "./evm-effectstream-l2/effectstream-l2-primitive.ts";
|
|
24
31
|
import { Erc721Primitive } from "./evm-erc721/erc721-primitive.ts";
|
|
25
32
|
import { Erc20Primitive } from "./evm-erc20/erc20-primitive.ts";
|
|
@@ -34,11 +41,17 @@ import { Nep245Primitive } from "./near-nep245/nep245-primitive.ts";
|
|
|
34
41
|
import { NearIntentPrimitive } from "./near-intent/near-intent-primitive.ts";
|
|
35
42
|
import { NearGenericPrimitive } from "./near-generic/near-generic-primitive.ts";
|
|
36
43
|
import { NearAccountWatchPrimitive } from "./near-account-watch/near-account-watch-primitive.ts";
|
|
44
|
+
import { CardanoMintBurnPrimitive } from "./cardano-mint-burn/mint-burn-primitive.ts";
|
|
45
|
+
import { CardanoTransferPrimitive } from "./cardano-transfer/transfer-primitive.ts";
|
|
46
|
+
import { CardanoPoolDelegationPrimitive } from "./cardano-pool-delegation/pool-delegation-primitive.ts";
|
|
47
|
+
import { CardanoDelayedAssetPrimitive } from "./cardano-delayed-asset/delayed-asset-primitive.ts";
|
|
48
|
+
import { CardanoProjectedNftPrimitive } from "./cardano-projected-nft/projected-nft-primitive.ts";
|
|
37
49
|
// import { EvmGenericPrimitive } from "./evm-generic/evm-generic-primitive.ts";
|
|
38
50
|
|
|
39
51
|
const builtInPrimitivesMap = {
|
|
40
52
|
[PrimitiveTypeMidnightGeneric]: MidnightGenericPrimitive,
|
|
41
53
|
[PrimitiveTypeMidnightNullifier]: MidnightNullifierPrimitive,
|
|
54
|
+
[PrimitiveTypeMidnightUnshieldedSpend]: MidnightUnshieldedSpendPrimitive,
|
|
42
55
|
[PrimitiveTypeEVMEffectstreamL2]: EffectstreamL2Primitive,
|
|
43
56
|
[PrimitiveTypeEVMERC721]: Erc721Primitive,
|
|
44
57
|
[PrimitiveTypeEVMERC20]: Erc20Primitive,
|
|
@@ -53,6 +66,11 @@ const builtInPrimitivesMap = {
|
|
|
53
66
|
[PrimitiveTypeNEARIntent]: NearIntentPrimitive,
|
|
54
67
|
[PrimitiveTypeNEARGeneric]: NearGenericPrimitive,
|
|
55
68
|
[PrimitiveTypeNEARAccountWatch]: NearAccountWatchPrimitive,
|
|
69
|
+
[PrimitiveTypeCardanoMintBurn]: CardanoMintBurnPrimitive,
|
|
70
|
+
[PrimitiveTypeCardanoTransfer]: CardanoTransferPrimitive,
|
|
71
|
+
[PrimitiveTypeCardanoPoolDelegation]: CardanoPoolDelegationPrimitive,
|
|
72
|
+
[PrimitiveTypeCardanoDelayedAsset]: CardanoDelayedAssetPrimitive,
|
|
73
|
+
[PrimitiveTypeCardanoProjectedNFT]: CardanoProjectedNftPrimitive,
|
|
56
74
|
// [PrimitiveTypeEVMGeneric]: EvmGenericPrimitive,
|
|
57
75
|
} as const;
|
|
58
76
|
|
|
@@ -63,6 +81,7 @@ export {
|
|
|
63
81
|
// Built-in Primitives
|
|
64
82
|
MidnightGenericPrimitive,
|
|
65
83
|
MidnightNullifierPrimitive,
|
|
84
|
+
MidnightUnshieldedSpendPrimitive,
|
|
66
85
|
EffectstreamL2Primitive,
|
|
67
86
|
Erc721Primitive,
|
|
68
87
|
Erc20Primitive,
|
|
@@ -77,5 +96,10 @@ export {
|
|
|
77
96
|
NearIntentPrimitive,
|
|
78
97
|
NearGenericPrimitive,
|
|
79
98
|
NearAccountWatchPrimitive,
|
|
99
|
+
CardanoMintBurnPrimitive,
|
|
100
|
+
CardanoTransferPrimitive,
|
|
101
|
+
CardanoPoolDelegationPrimitive,
|
|
102
|
+
CardanoDelayedAssetPrimitive,
|
|
103
|
+
CardanoProjectedNftPrimitive,
|
|
80
104
|
// EvmGenericPrimitive,
|
|
81
105
|
};
|
package/types.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
//import type { AppEvents } from "@effectstream/events";
|
|
2
|
-
|
|
3
1
|
import type { PreparedQuery } from "@pgtyped/runtime";
|
|
4
2
|
import type {
|
|
5
3
|
AddressType,
|
|
@@ -8,11 +6,27 @@ import type {
|
|
|
8
6
|
WalletAddress,
|
|
9
7
|
} from "@effectstream/utils";
|
|
10
8
|
import type { Prando } from "@effectstream/crypto";
|
|
9
|
+
import type { EventPathAndDef, ResolvedPath } from "@effectstream/event-client";
|
|
10
|
+
import type { Static } from "@sinclair/typebox";
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Closure passed to every state transition for emitting custom app events.
|
|
14
|
+
*
|
|
15
|
+
* - The runtime collects events into a per-input buffer during STF execution.
|
|
16
|
+
* - On STF success, events are promoted to the per-block buffer.
|
|
17
|
+
* - After the block's `COMMIT` succeeds, events are flushed to MQTT.
|
|
18
|
+
* - On STF failure or block-level `ROLLBACK`, events are dropped.
|
|
19
|
+
*
|
|
20
|
+
* `blockHeight` is auto-injected by `registerEvents` and auto-filled by the
|
|
21
|
+
* runtime — apps omit it from the payload.
|
|
22
|
+
*
|
|
23
|
+
* See plan: /Users/edwardalvarado/.claude/plans/wild-kindling-reddy.md
|
|
24
|
+
*/
|
|
25
|
+
export type EmitFn = <E extends EventPathAndDef>(
|
|
26
|
+
event: E,
|
|
27
|
+
payload: Omit<Static<E["type"]> & ResolvedPath<E["path"]>, "blockHeight">,
|
|
28
|
+
) => void;
|
|
14
29
|
|
|
15
|
-
// TODO: replace any
|
|
16
30
|
export type BaseStfInput = {
|
|
17
31
|
blockHeight: EffectstreamBlockNumber;
|
|
18
32
|
blockTimestamp: TimestampMs;
|
|
@@ -21,7 +35,15 @@ export type BaseStfInput = {
|
|
|
21
35
|
signerAddress?: WalletAddress;
|
|
22
36
|
signerAddressType?: AddressType;
|
|
23
37
|
randomGenerator: Prando;
|
|
38
|
+
/** Emit a custom app event. Delivered to MQTT after the block commits. */
|
|
39
|
+
emit: EmitFn;
|
|
24
40
|
};
|
|
41
|
+
|
|
42
|
+
// Retained for compatibility with the existing `Stm<Grammar, Events>` generic
|
|
43
|
+
// parameter. Future work: thread a real registered-events union through here so
|
|
44
|
+
// `data.emit` is restricted to the app's declared events.
|
|
45
|
+
export type AppEvents = any;
|
|
46
|
+
|
|
25
47
|
export type BaseStfOutput<Events extends AppEvents> = {
|
|
26
48
|
stateTransitions: [PreparedQuery<any, any>, any][];
|
|
27
49
|
events: Events[];
|