@effectstream/frontend-sdk 0.104.0 → 0.200.1
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/mod.js +145 -124
- package/package.json +2 -2
package/dist/mod.js
CHANGED
|
@@ -48,20 +48,20 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
48
48
|
// node:buffer
|
|
49
49
|
var exports_buffer = {};
|
|
50
50
|
__export(exports_buffer, {
|
|
51
|
-
|
|
52
|
-
resolveObjectURL: () => resolveObjectURL,
|
|
53
|
-
kStringMaxLength: () => kStringMaxLength,
|
|
54
|
-
kMaxLength: () => kMaxLength,
|
|
55
|
-
isUtf8: () => isUtf8,
|
|
56
|
-
isAscii: () => isAscii,
|
|
57
|
-
default: () => buffer_default,
|
|
58
|
-
constants: () => constants,
|
|
59
|
-
btoa: () => btoa,
|
|
60
|
-
atob: () => atob,
|
|
61
|
-
INSPECT_MAX_BYTES: () => INSPECT_MAX_BYTES,
|
|
62
|
-
File: () => File,
|
|
51
|
+
Blob: () => Blob,
|
|
63
52
|
Buffer: () => Buffer2,
|
|
64
|
-
|
|
53
|
+
File: () => File,
|
|
54
|
+
INSPECT_MAX_BYTES: () => INSPECT_MAX_BYTES,
|
|
55
|
+
atob: () => atob,
|
|
56
|
+
btoa: () => btoa,
|
|
57
|
+
constants: () => constants,
|
|
58
|
+
default: () => buffer_default,
|
|
59
|
+
isAscii: () => isAscii,
|
|
60
|
+
isUtf8: () => isUtf8,
|
|
61
|
+
kMaxLength: () => kMaxLength,
|
|
62
|
+
kStringMaxLength: () => kStringMaxLength,
|
|
63
|
+
resolveObjectURL: () => resolveObjectURL,
|
|
64
|
+
transcode: () => transcode
|
|
65
65
|
});
|
|
66
66
|
function getLens(b64) {
|
|
67
67
|
var len2 = b64.length;
|
|
@@ -1384,35 +1384,35 @@ var init_buffer = __esm(() => {
|
|
|
1384
1384
|
// node:util
|
|
1385
1385
|
var exports_util = {};
|
|
1386
1386
|
__export(exports_util, {
|
|
1387
|
-
|
|
1388
|
-
promisify: () => promisify,
|
|
1389
|
-
log: () => log,
|
|
1390
|
-
isUndefined: () => isUndefined,
|
|
1391
|
-
isSymbol: () => isSymbol,
|
|
1392
|
-
isString: () => isString,
|
|
1393
|
-
isRegExp: () => isRegExp,
|
|
1394
|
-
isPrimitive: () => isPrimitive,
|
|
1395
|
-
isObject: () => isObject,
|
|
1396
|
-
isNumber: () => isNumber,
|
|
1397
|
-
isNullOrUndefined: () => isNullOrUndefined,
|
|
1398
|
-
isNull: () => isNull,
|
|
1399
|
-
isFunction: () => isFunction,
|
|
1400
|
-
isError: () => isError,
|
|
1401
|
-
isDate: () => isDate,
|
|
1402
|
-
isBuffer: () => isBuffer,
|
|
1403
|
-
isBoolean: () => isBoolean,
|
|
1404
|
-
isArray: () => isArray,
|
|
1405
|
-
inspect: () => inspect,
|
|
1406
|
-
inherits: () => inherits,
|
|
1407
|
-
format: () => format,
|
|
1408
|
-
deprecate: () => deprecate,
|
|
1409
|
-
default: () => util_default,
|
|
1410
|
-
debuglog: () => debuglog,
|
|
1411
|
-
callbackifyOnRejected: () => callbackifyOnRejected,
|
|
1412
|
-
callbackify: () => callbackify,
|
|
1413
|
-
_extend: () => _extend,
|
|
1387
|
+
TextDecoder: () => TextDecoder2,
|
|
1414
1388
|
TextEncoder: () => TextEncoder2,
|
|
1415
|
-
|
|
1389
|
+
_extend: () => _extend,
|
|
1390
|
+
callbackify: () => callbackify,
|
|
1391
|
+
callbackifyOnRejected: () => callbackifyOnRejected,
|
|
1392
|
+
debuglog: () => debuglog,
|
|
1393
|
+
default: () => util_default,
|
|
1394
|
+
deprecate: () => deprecate,
|
|
1395
|
+
format: () => format,
|
|
1396
|
+
inherits: () => inherits,
|
|
1397
|
+
inspect: () => inspect,
|
|
1398
|
+
isArray: () => isArray,
|
|
1399
|
+
isBoolean: () => isBoolean,
|
|
1400
|
+
isBuffer: () => isBuffer,
|
|
1401
|
+
isDate: () => isDate,
|
|
1402
|
+
isError: () => isError,
|
|
1403
|
+
isFunction: () => isFunction,
|
|
1404
|
+
isNull: () => isNull,
|
|
1405
|
+
isNullOrUndefined: () => isNullOrUndefined,
|
|
1406
|
+
isNumber: () => isNumber,
|
|
1407
|
+
isObject: () => isObject,
|
|
1408
|
+
isPrimitive: () => isPrimitive,
|
|
1409
|
+
isRegExp: () => isRegExp,
|
|
1410
|
+
isString: () => isString,
|
|
1411
|
+
isSymbol: () => isSymbol,
|
|
1412
|
+
isUndefined: () => isUndefined,
|
|
1413
|
+
log: () => log,
|
|
1414
|
+
promisify: () => promisify,
|
|
1415
|
+
types: () => types
|
|
1416
1416
|
});
|
|
1417
1417
|
function format(f, ...args) {
|
|
1418
1418
|
if (!isString(f)) {
|
|
@@ -1794,16 +1794,16 @@ var init_util = __esm(() => {
|
|
|
1794
1794
|
// node:events
|
|
1795
1795
|
var exports_events = {};
|
|
1796
1796
|
__export(exports_events, {
|
|
1797
|
-
|
|
1798
|
-
once: () => once2,
|
|
1799
|
-
listenerCount: () => listenerCount2,
|
|
1800
|
-
init: () => EventEmitter,
|
|
1801
|
-
getMaxListeners: () => getMaxListeners2,
|
|
1802
|
-
getEventListeners: () => getEventListeners,
|
|
1803
|
-
default: () => events_default,
|
|
1804
|
-
captureRejectionSymbol: () => captureRejectionSymbol,
|
|
1797
|
+
EventEmitter: () => EventEmitter,
|
|
1805
1798
|
addAbortListener: () => addAbortListener,
|
|
1806
|
-
|
|
1799
|
+
captureRejectionSymbol: () => captureRejectionSymbol,
|
|
1800
|
+
default: () => events_default,
|
|
1801
|
+
getEventListeners: () => getEventListeners,
|
|
1802
|
+
getMaxListeners: () => getMaxListeners2,
|
|
1803
|
+
init: () => EventEmitter,
|
|
1804
|
+
listenerCount: () => listenerCount2,
|
|
1805
|
+
once: () => once2,
|
|
1806
|
+
setMaxListeners: () => setMaxListeners2
|
|
1807
1807
|
});
|
|
1808
1808
|
function emitError(emitter, args) {
|
|
1809
1809
|
var { _events: events } = emitter;
|
|
@@ -2165,7 +2165,7 @@ var init_events = __esm(() => {
|
|
|
2165
2165
|
});
|
|
2166
2166
|
|
|
2167
2167
|
// node:stream
|
|
2168
|
-
var require_stream = __commonJS((exports, module)
|
|
2168
|
+
var require_stream = __commonJS(function(exports, module) {
|
|
2169
2169
|
var __commonJS2 = (cb, mod2) => () => (mod2 || cb((mod2 = { exports: {} }).exports, mod2), mod2.exports);
|
|
2170
2170
|
var require_primordials = __commonJS2((exports2, module2) => {
|
|
2171
2171
|
|
|
@@ -6089,51 +6089,51 @@ var require_stream = __commonJS((exports, module) => {
|
|
|
6089
6089
|
// node:crypto
|
|
6090
6090
|
var exports_crypto = {};
|
|
6091
6091
|
__export(exports_crypto, {
|
|
6092
|
-
|
|
6093
|
-
rng: () => rng2,
|
|
6094
|
-
randomUUID: () => randomUUID,
|
|
6095
|
-
randomFillSync: () => randomFillSync2,
|
|
6096
|
-
randomFill: () => randomFill2,
|
|
6097
|
-
randomBytes: () => randomBytes2,
|
|
6098
|
-
publicEncrypt: () => publicEncrypt2,
|
|
6099
|
-
publicDecrypt: () => publicDecrypt2,
|
|
6100
|
-
pseudoRandomBytes: () => pseudoRandomBytes2,
|
|
6101
|
-
prng: () => prng2,
|
|
6102
|
-
privateEncrypt: () => privateEncrypt2,
|
|
6103
|
-
privateDecrypt: () => privateDecrypt2,
|
|
6104
|
-
pbkdf2Sync: () => pbkdf2Sync2,
|
|
6105
|
-
pbkdf2: () => pbkdf22,
|
|
6106
|
-
listCiphers: () => listCiphers2,
|
|
6107
|
-
getRandomValues: () => getRandomValues,
|
|
6108
|
-
getHashes: () => getHashes2,
|
|
6109
|
-
getDiffieHellman: () => getDiffieHellman2,
|
|
6110
|
-
getCurves: () => getCurves,
|
|
6111
|
-
getCiphers: () => getCiphers2,
|
|
6112
|
-
default: () => crypto_default,
|
|
6113
|
-
createVerify: () => createVerify2,
|
|
6114
|
-
createSign: () => createSign2,
|
|
6115
|
-
createHmac: () => createHmac2,
|
|
6116
|
-
createHash: () => createHash2,
|
|
6117
|
-
createECDH: () => createECDH2,
|
|
6118
|
-
createDiffieHellmanGroup: () => createDiffieHellmanGroup2,
|
|
6119
|
-
createDiffieHellman: () => createDiffieHellman2,
|
|
6120
|
-
createDecipheriv: () => createDecipheriv2,
|
|
6121
|
-
createDecipher: () => createDecipher2,
|
|
6122
|
-
createCredentials: () => createCredentials2,
|
|
6123
|
-
createCipheriv: () => createCipheriv2,
|
|
6124
|
-
createCipher: () => createCipher2,
|
|
6125
|
-
constants: () => constants2,
|
|
6126
|
-
Verify: () => Verify2,
|
|
6127
|
-
Sign: () => Sign2,
|
|
6128
|
-
Hmac: () => Hmac2,
|
|
6129
|
-
Hash: () => Hash2,
|
|
6130
|
-
DiffieHellmanGroup: () => DiffieHellmanGroup2,
|
|
6131
|
-
DiffieHellman: () => DiffieHellman2,
|
|
6132
|
-
Decipheriv: () => Decipheriv2,
|
|
6133
|
-
Decipher: () => Decipher2,
|
|
6134
|
-
DEFAULT_ENCODING: () => DEFAULT_ENCODING,
|
|
6092
|
+
Cipher: () => Cipher2,
|
|
6135
6093
|
Cipheriv: () => Cipheriv2,
|
|
6136
|
-
|
|
6094
|
+
DEFAULT_ENCODING: () => DEFAULT_ENCODING,
|
|
6095
|
+
Decipher: () => Decipher2,
|
|
6096
|
+
Decipheriv: () => Decipheriv2,
|
|
6097
|
+
DiffieHellman: () => DiffieHellman2,
|
|
6098
|
+
DiffieHellmanGroup: () => DiffieHellmanGroup2,
|
|
6099
|
+
Hash: () => Hash2,
|
|
6100
|
+
Hmac: () => Hmac2,
|
|
6101
|
+
Sign: () => Sign2,
|
|
6102
|
+
Verify: () => Verify2,
|
|
6103
|
+
constants: () => constants2,
|
|
6104
|
+
createCipher: () => createCipher2,
|
|
6105
|
+
createCipheriv: () => createCipheriv2,
|
|
6106
|
+
createCredentials: () => createCredentials2,
|
|
6107
|
+
createDecipher: () => createDecipher2,
|
|
6108
|
+
createDecipheriv: () => createDecipheriv2,
|
|
6109
|
+
createDiffieHellman: () => createDiffieHellman2,
|
|
6110
|
+
createDiffieHellmanGroup: () => createDiffieHellmanGroup2,
|
|
6111
|
+
createECDH: () => createECDH2,
|
|
6112
|
+
createHash: () => createHash2,
|
|
6113
|
+
createHmac: () => createHmac2,
|
|
6114
|
+
createSign: () => createSign2,
|
|
6115
|
+
createVerify: () => createVerify2,
|
|
6116
|
+
default: () => crypto_default,
|
|
6117
|
+
getCiphers: () => getCiphers2,
|
|
6118
|
+
getCurves: () => getCurves,
|
|
6119
|
+
getDiffieHellman: () => getDiffieHellman2,
|
|
6120
|
+
getHashes: () => getHashes2,
|
|
6121
|
+
getRandomValues: () => getRandomValues,
|
|
6122
|
+
listCiphers: () => listCiphers2,
|
|
6123
|
+
pbkdf2: () => pbkdf22,
|
|
6124
|
+
pbkdf2Sync: () => pbkdf2Sync2,
|
|
6125
|
+
privateDecrypt: () => privateDecrypt2,
|
|
6126
|
+
privateEncrypt: () => privateEncrypt2,
|
|
6127
|
+
prng: () => prng2,
|
|
6128
|
+
pseudoRandomBytes: () => pseudoRandomBytes2,
|
|
6129
|
+
publicDecrypt: () => publicDecrypt2,
|
|
6130
|
+
publicEncrypt: () => publicEncrypt2,
|
|
6131
|
+
randomBytes: () => randomBytes2,
|
|
6132
|
+
randomFill: () => randomFill2,
|
|
6133
|
+
randomFillSync: () => randomFillSync2,
|
|
6134
|
+
randomUUID: () => randomUUID,
|
|
6135
|
+
rng: () => rng2,
|
|
6136
|
+
webcrypto: () => webcrypto
|
|
6137
6137
|
});
|
|
6138
6138
|
function __accessProp2(key) {
|
|
6139
6139
|
return this[key];
|
|
@@ -18885,6 +18885,13 @@ class EvmCrypto {
|
|
|
18885
18885
|
}
|
|
18886
18886
|
}
|
|
18887
18887
|
|
|
18888
|
+
// ../effectstream-sdk/utils/src/polkadot-esm-cjs-warning.ts
|
|
18889
|
+
var FLAG = "POLKADOTJS_DISABLE_ESM_CJS_WARNING";
|
|
18890
|
+
var env = globalThis.process?.env;
|
|
18891
|
+
if (env && env[FLAG] === undefined) {
|
|
18892
|
+
env[FLAG] = "1";
|
|
18893
|
+
}
|
|
18894
|
+
|
|
18888
18895
|
// ../effectstream-sdk/crypto/src/chains/polkadot.ts
|
|
18889
18896
|
import { Value as Value5 } from "@sinclair/typebox/value";
|
|
18890
18897
|
import { cryptoWaitReady, decodeAddress as decodeAddress2, signatureVerify } from "@polkadot/util-crypto";
|
|
@@ -18967,14 +18974,22 @@ class MidnightCrypto {
|
|
|
18967
18974
|
if (!signature || !verifyingKey)
|
|
18968
18975
|
return false;
|
|
18969
18976
|
const [ledgerMod, addrMod] = await Promise.all([
|
|
18970
|
-
import("@
|
|
18977
|
+
import("@midnightntwrk/ledger-v9"),
|
|
18971
18978
|
import("@midnightntwrk/wallet-sdk-address-format")
|
|
18972
18979
|
]);
|
|
18973
|
-
const
|
|
18980
|
+
const taggedVerifyingKey = {
|
|
18981
|
+
tag: "schnorr",
|
|
18982
|
+
value: verifyingKey
|
|
18983
|
+
};
|
|
18984
|
+
const taggedSignature = {
|
|
18985
|
+
tag: "schnorr",
|
|
18986
|
+
value: signature
|
|
18987
|
+
};
|
|
18988
|
+
const expectedHexAddress = ledgerMod.addressFromKey(taggedVerifyingKey).toLowerCase();
|
|
18974
18989
|
let decodedHex;
|
|
18975
18990
|
try {
|
|
18976
18991
|
const bech323 = addrMod.MidnightBech32m.parse(signerAddress);
|
|
18977
|
-
const decoded =
|
|
18992
|
+
const decoded = bech323.decode(addrMod.UnshieldedAddress, bech323.network);
|
|
18978
18993
|
decodedHex = decoded.hexString.toLowerCase();
|
|
18979
18994
|
} catch {
|
|
18980
18995
|
return false;
|
|
@@ -18982,7 +18997,7 @@ class MidnightCrypto {
|
|
|
18982
18997
|
if (decodedHex !== expectedHexAddress)
|
|
18983
18998
|
return false;
|
|
18984
18999
|
const messageBytes = new TextEncoder().encode(message);
|
|
18985
|
-
return ledgerMod.verifySignature(
|
|
19000
|
+
return ledgerMod.verifySignature(taggedVerifyingKey, messageBytes, taggedSignature);
|
|
18986
19001
|
} catch (err) {
|
|
18987
19002
|
console.error("[MidnightCrypto] error verifying signature:", err);
|
|
18988
19003
|
return false;
|
|
@@ -20597,16 +20612,16 @@ class MidnightLocalConnector {
|
|
|
20597
20612
|
const { hdMod, keystoreMod } = await loadKeystoreDeps();
|
|
20598
20613
|
const seed = args.seed ?? generateRandomHexSeed(32);
|
|
20599
20614
|
const unshieldedSeed = deriveUnshieldedSeed(hdMod, seed, hdMod.Roles.NightExternal);
|
|
20600
|
-
const unshieldedKeystore = keystoreMod.createKeystore(unshieldedSeed, args.networkId);
|
|
20615
|
+
const unshieldedKeystore = keystoreMod.createKeystore({ kind: "schnorr", secret: unshieldedSeed }, args.networkId);
|
|
20601
20616
|
const unshieldedAddress = unshieldedKeystore.getBech32Address().asString();
|
|
20602
|
-
const verifyingKey =
|
|
20617
|
+
const verifyingKey = schnorrValue(unshieldedKeystore.getPublicKey(), "verifying key");
|
|
20603
20618
|
const api = {
|
|
20604
20619
|
signData: async (data, options) => {
|
|
20605
20620
|
const bytes = options.encoding === "hex" ? Buffer2.from(data, "hex") : Buffer2.from(data, "utf-8");
|
|
20606
|
-
const signature = unshieldedKeystore.signData(bytes);
|
|
20621
|
+
const signature = schnorrValue(unshieldedKeystore.signData(bytes), "signature");
|
|
20607
20622
|
return {
|
|
20608
20623
|
data,
|
|
20609
|
-
signature
|
|
20624
|
+
signature,
|
|
20610
20625
|
verifyingKey
|
|
20611
20626
|
};
|
|
20612
20627
|
},
|
|
@@ -20634,8 +20649,8 @@ class MidnightLocalConnector {
|
|
|
20634
20649
|
const { hdMod, keystoreMod } = await loadKeystoreDeps();
|
|
20635
20650
|
const seed = args.seed ?? generateRandomHexSeed(32);
|
|
20636
20651
|
const unshieldedSeed = deriveUnshieldedSeed(hdMod, seed, hdMod.Roles.NightExternal);
|
|
20637
|
-
const unshieldedKeystore = keystoreMod.createKeystore(unshieldedSeed, args.networkId);
|
|
20638
|
-
const verifyingKey =
|
|
20652
|
+
const unshieldedKeystore = keystoreMod.createKeystore({ kind: "schnorr", secret: unshieldedSeed }, args.networkId);
|
|
20653
|
+
const verifyingKey = schnorrValue(unshieldedKeystore.getPublicKey(), "verifying key");
|
|
20639
20654
|
const fullNetworkUrls = {
|
|
20640
20655
|
indexer: networkUrls.indexer,
|
|
20641
20656
|
indexerWS: networkUrls.indexerWS,
|
|
@@ -20650,10 +20665,10 @@ class MidnightLocalConnector {
|
|
|
20650
20665
|
const api = {
|
|
20651
20666
|
signData: async (data, options) => {
|
|
20652
20667
|
const bytes = options.encoding === "hex" ? Buffer2.from(data, "hex") : Buffer2.from(data, "utf-8");
|
|
20653
|
-
const signature = unshieldedKeystore.signData(bytes);
|
|
20668
|
+
const signature = schnorrValue(unshieldedKeystore.signData(bytes), "signature");
|
|
20654
20669
|
return {
|
|
20655
20670
|
data,
|
|
20656
|
-
signature
|
|
20671
|
+
signature,
|
|
20657
20672
|
verifyingKey
|
|
20658
20673
|
};
|
|
20659
20674
|
},
|
|
@@ -20745,6 +20760,12 @@ function generateRandomHexSeed(byteLength2) {
|
|
|
20745
20760
|
crypto.getRandomValues(bytes);
|
|
20746
20761
|
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
20747
20762
|
}
|
|
20763
|
+
function schnorrValue(value, label) {
|
|
20764
|
+
if (value.tag !== "schnorr") {
|
|
20765
|
+
throw new Error(`Expected Schnorr ${label}, received ${value.tag}`);
|
|
20766
|
+
}
|
|
20767
|
+
return value.value;
|
|
20768
|
+
}
|
|
20748
20769
|
|
|
20749
20770
|
// ../effectstream-sdk/wallets/src/solana/solana.ts
|
|
20750
20771
|
import { getWallets } from "@wallet-standard/app";
|
|
@@ -22561,22 +22582,22 @@ async function sendBatcherTransaction(wallet, conciseData, effectstreamConfig, w
|
|
|
22561
22582
|
};
|
|
22562
22583
|
}
|
|
22563
22584
|
export {
|
|
22564
|
-
|
|
22565
|
-
waitForEffectstreamBlockProcessed,
|
|
22566
|
-
signMessage,
|
|
22567
|
-
sendTransaction,
|
|
22568
|
-
sendSelfSequencedTransaction,
|
|
22569
|
-
sendBatcherTransaction,
|
|
22570
|
-
pickWalletMode,
|
|
22571
|
-
midnightLocalIcon,
|
|
22572
|
-
getAddressType,
|
|
22573
|
-
formatError2 as formatError,
|
|
22574
|
-
evmViemIcon,
|
|
22575
|
-
cardanoLocalIcon,
|
|
22576
|
-
allInjectedWallets,
|
|
22577
|
-
accountPayload_,
|
|
22578
|
-
accountMessages,
|
|
22579
|
-
WalletNameMap,
|
|
22585
|
+
EffectstreamConfig,
|
|
22580
22586
|
WalletMode,
|
|
22581
|
-
|
|
22587
|
+
WalletNameMap,
|
|
22588
|
+
accountMessages,
|
|
22589
|
+
accountPayload_,
|
|
22590
|
+
allInjectedWallets,
|
|
22591
|
+
cardanoLocalIcon,
|
|
22592
|
+
evmViemIcon,
|
|
22593
|
+
formatError2 as formatError,
|
|
22594
|
+
getAddressType,
|
|
22595
|
+
midnightLocalIcon,
|
|
22596
|
+
pickWalletMode,
|
|
22597
|
+
sendBatcherTransaction,
|
|
22598
|
+
sendSelfSequencedTransaction,
|
|
22599
|
+
sendTransaction,
|
|
22600
|
+
signMessage,
|
|
22601
|
+
waitForEffectstreamBlockProcessed,
|
|
22602
|
+
walletLogin
|
|
22582
22603
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effectstream/frontend-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.200.1",
|
|
4
4
|
"license": "(MIT OR Apache-2.0)",
|
|
5
5
|
"homepage": "https://effectstream.github.io/docs/",
|
|
6
6
|
"repository": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"build": "bun run build.ts"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@effectstream/wallets": "0.
|
|
32
|
+
"@effectstream/wallets": "0.200.1"
|
|
33
33
|
},
|
|
34
34
|
"description": "React frontend SDK for EffectStream"
|
|
35
35
|
}
|