@unicitylabs/sphere-sdk 0.17.2-dev.2 → 0.17.2
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/connect/index.cjs +7 -4
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.d.cts +4 -0
- package/dist/connect/index.d.ts +4 -0
- package/dist/connect/index.js +7 -4
- package/dist/connect/index.js.map +1 -1
- package/dist/core/index.cjs +69 -22
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +2 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +69 -22
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/connect/index.cjs +1 -1
- package/dist/impl/browser/connect/index.cjs.map +1 -1
- package/dist/impl/browser/connect/index.js +1 -1
- package/dist/impl/browser/connect/index.js.map +1 -1
- package/dist/impl/wallet-api-v2/index.cjs +3 -0
- package/dist/impl/wallet-api-v2/index.cjs.map +1 -1
- package/dist/impl/wallet-api-v2/index.js +3 -0
- package/dist/impl/wallet-api-v2/index.js.map +1 -1
- package/dist/index.cjs +88 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.js +85 -22
- package/dist/index.js.map +1 -1
- package/dist/modules/payments-v2/index.cjs +40 -6
- package/dist/modules/payments-v2/index.cjs.map +1 -1
- package/dist/modules/payments-v2/index.d.cts +22 -1
- package/dist/modules/payments-v2/index.d.ts +22 -1
- package/dist/modules/payments-v2/index.js +37 -6
- package/dist/modules/payments-v2/index.js.map +1 -1
- package/dist/token-engine/index.cjs +67 -21
- package/dist/token-engine/index.cjs.map +1 -1
- package/dist/token-engine/index.d.cts +28 -4
- package/dist/token-engine/index.d.ts +28 -4
- package/dist/token-engine/index.js +64 -21
- package/dist/token-engine/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -50,6 +50,7 @@ __export(index_exports, {
|
|
|
50
50
|
LIMITS: () => LIMITS,
|
|
51
51
|
MarketModule: () => MarketModule,
|
|
52
52
|
NETWORKS: () => NETWORKS,
|
|
53
|
+
NFT_DOCUMENT_MEDIA_TYPE: () => NFT_DOCUMENT_MEDIA_TYPE,
|
|
53
54
|
NFT_LINK_TAG: () => NFT_LINK_TAG,
|
|
54
55
|
NFT_MAX_PAYLOAD_BYTES: () => NFT_MAX_PAYLOAD_BYTES,
|
|
55
56
|
NFT_MEDIA_TAG: () => NFT_MEDIA_TAG,
|
|
@@ -128,6 +129,7 @@ __export(index_exports, {
|
|
|
128
129
|
identityFromMnemonicSync: () => identityFromMnemonicSync,
|
|
129
130
|
initSphere: () => initSphere,
|
|
130
131
|
isKnownToken: () => isKnownToken,
|
|
132
|
+
isNftDocumentLink: () => isNftDocumentLink,
|
|
131
133
|
isPhoneNumber: () => import_nostr_js_sdk5.isPhoneNumber,
|
|
132
134
|
isPossiblyCommittedSendOutcome: () => isPossiblyCommittedSendOutcome,
|
|
133
135
|
isSphereError: () => isSphereError,
|
|
@@ -145,6 +147,7 @@ __export(index_exports, {
|
|
|
145
147
|
normalizeNametag: () => import_nostr_js_sdk5.normalizeNametag,
|
|
146
148
|
parseAddress: () => parseAddress,
|
|
147
149
|
parseAndDecryptWalletText: () => parseAndDecryptWalletText,
|
|
150
|
+
parseNftDocument: () => parseNftDocument,
|
|
148
151
|
parseNftPayload: () => parseNftPayload,
|
|
149
152
|
parseTokenAmount: () => parseTokenAmount,
|
|
150
153
|
parseWalletText: () => parseWalletText,
|
|
@@ -4693,6 +4696,26 @@ var GroupVisibility = {
|
|
|
4693
4696
|
PRIVATE: "PRIVATE"
|
|
4694
4697
|
};
|
|
4695
4698
|
|
|
4699
|
+
// modules/groupchat/group-id.ts
|
|
4700
|
+
var MAX_SLUG_LENGTH = 24;
|
|
4701
|
+
var RANDOM_BYTES = 8;
|
|
4702
|
+
function groupIdSlug(name) {
|
|
4703
|
+
const slug = name.normalize("NFKD").replace(/\p{M}/gu, "").toLowerCase().replace(/['\u2019]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
4704
|
+
if (slug.length <= MAX_SLUG_LENGTH) return slug;
|
|
4705
|
+
const head = slug.slice(0, MAX_SLUG_LENGTH + 1);
|
|
4706
|
+
const hyphen = head.lastIndexOf("-");
|
|
4707
|
+
return hyphen > 0 ? head.slice(0, hyphen) : slug.slice(0, MAX_SLUG_LENGTH);
|
|
4708
|
+
}
|
|
4709
|
+
function newGroupId(name) {
|
|
4710
|
+
const crypto2 = globalThis.crypto;
|
|
4711
|
+
if (typeof crypto2?.getRandomValues !== "function") {
|
|
4712
|
+
throw new SphereError("Creating a group requires crypto.getRandomValues", "INVALID_CONFIG");
|
|
4713
|
+
}
|
|
4714
|
+
const bytes = crypto2.getRandomValues(new Uint8Array(RANDOM_BYTES));
|
|
4715
|
+
const random = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
4716
|
+
return `${groupIdSlug(name) || "group"}-${random}`;
|
|
4717
|
+
}
|
|
4718
|
+
|
|
4696
4719
|
// modules/groupchat/GroupChatModule.ts
|
|
4697
4720
|
function createNip29Filter(data) {
|
|
4698
4721
|
return new import_nostr_js_sdk3.Filter(data);
|
|
@@ -5304,9 +5327,9 @@ var GroupChatModule = class {
|
|
|
5304
5327
|
if (!this.client) return null;
|
|
5305
5328
|
const creatorPubkey = this.getMyPublicKey();
|
|
5306
5329
|
if (!creatorPubkey) return null;
|
|
5307
|
-
const proposedGroupId = options.name.toLowerCase().replace(/[^a-z0-9]/g, "").slice(0, 20) || this.randomId();
|
|
5308
5330
|
try {
|
|
5309
5331
|
const isPrivate = options.visibility === GroupVisibility.PRIVATE;
|
|
5332
|
+
const proposedGroupId = newGroupId(options.name);
|
|
5310
5333
|
const eventId = await this.client.createAndPublishEvent({
|
|
5311
5334
|
kind: NIP29_KINDS.CREATE_GROUP,
|
|
5312
5335
|
tags: [["h", proposedGroupId]],
|
|
@@ -9937,7 +9960,8 @@ var NFT_MEDIA_TAG = 39053n;
|
|
|
9937
9960
|
var NFT_LINK_TAG = 39054n;
|
|
9938
9961
|
var NFT_SIGNED_TAG = 39055n;
|
|
9939
9962
|
var NFT_FORMAT_VERSION = 1n;
|
|
9940
|
-
var
|
|
9963
|
+
var NFT_DOCUMENT_MEDIA_TYPE = "application/vnd.unicity.nft+cbor";
|
|
9964
|
+
var METADATA_ARITY = 9;
|
|
9941
9965
|
var MEDIA_ARITY = 3;
|
|
9942
9966
|
var LINK_ARITY = 4;
|
|
9943
9967
|
var SIGNED_ARITY = 4;
|
|
@@ -9945,12 +9969,15 @@ var CREATOR_BYTES = 33;
|
|
|
9945
9969
|
var SIGNATURE_BYTES = 65;
|
|
9946
9970
|
var MAX_URI_LENGTH = 2048;
|
|
9947
9971
|
var LINK_SCHEMES = ["https://", "ipfs://", "ar://"];
|
|
9948
|
-
var SIGNED_DOMAIN = "
|
|
9972
|
+
var SIGNED_DOMAIN = new TextEncoder().encode("UNICITY_NFT_SIGNED");
|
|
9949
9973
|
var MEDIA_TYPE_PATTERN = /^[a-z0-9][a-z0-9!#$&^_.+-]{0,126}\/[a-z0-9][a-z0-9!#$&^_.+-]{0,126}$/;
|
|
9950
9974
|
var SHA256_HEX_PATTERN = /^[0-9a-f]{64}$/i;
|
|
9975
|
+
var COLLECTION_ID_PATTERN = /^(?:[0-9a-f]{2}){1,64}$/i;
|
|
9951
9976
|
var LONE_SURROGATE = /\p{Cs}/u;
|
|
9952
9977
|
var CBOR_MAJOR_TYPE_MASK = 224;
|
|
9953
9978
|
var ATTRIBUTE_VALUE_RULE = "must be non-empty text or an integer within \xB1(2^53 \u2212 1) \u2014 write decimals and larger numbers as text";
|
|
9979
|
+
var COLLECTION_ID_RULE = "must be null or 1\u201364 bytes as even-length hex (2\u2013128 characters)";
|
|
9980
|
+
var DOCUMENT_AS_MEDIA_RULE = `must not be ${NFT_DOCUMENT_MEDIA_TYPE}: a document link is a token's content, never media`;
|
|
9954
9981
|
var UTF8 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
|
|
9955
9982
|
function refuse(field, rule, cause) {
|
|
9956
9983
|
return new SphereError(`Invalid NFT ${field}: ${rule}`, "VALIDATION_ERROR", cause);
|
|
@@ -9962,6 +9989,7 @@ var fieldName = (prefix, name) => prefix === "" ? name : `${prefix}.${name}`;
|
|
|
9962
9989
|
var isText = (value) => typeof value === "string" && value.length > 0 && !LONE_SURROGATE.test(value);
|
|
9963
9990
|
var isBytes3 = (value, length) => value instanceof Uint8Array && (length === void 0 ? value.length > 0 : value.length === length);
|
|
9964
9991
|
var isMediaType = (value) => typeof value === "string" && MEDIA_TYPE_PATTERN.test(value);
|
|
9992
|
+
var isCollectionId = (value) => typeof value === "string" && COLLECTION_ID_PATTERN.test(value);
|
|
9965
9993
|
var isAttributeValue = (value) => typeof value === "number" ? Number.isSafeInteger(value) : isText(value);
|
|
9966
9994
|
function hasSpaceOrControl(value) {
|
|
9967
9995
|
for (let i = 0; i < value.length; i++) {
|
|
@@ -10004,8 +10032,9 @@ function checkLink(prefix, link) {
|
|
|
10004
10032
|
function checkMediaRef(field, ref) {
|
|
10005
10033
|
if (ref === null) return;
|
|
10006
10034
|
if (ref?.kind === "media") return checkMedia(field, ref);
|
|
10007
|
-
if (ref?.kind
|
|
10008
|
-
|
|
10035
|
+
if (ref?.kind !== "link") throw refuse(field, "must be an NftMedia, an NftLink or null");
|
|
10036
|
+
checkLink(field, ref);
|
|
10037
|
+
ensure(!isNftDocumentLink(ref), fieldName(field, "media_type"), DOCUMENT_AS_MEDIA_RULE);
|
|
10009
10038
|
}
|
|
10010
10039
|
function checkAttributes(attributes) {
|
|
10011
10040
|
ensure(Array.isArray(attributes), "attributes", "must be an array \u2014 [] when there are none");
|
|
@@ -10022,6 +10051,7 @@ function checkMetadata(metadata) {
|
|
|
10022
10051
|
checkOptionalText("external_url", metadata.external_url);
|
|
10023
10052
|
checkAttributes(metadata.attributes);
|
|
10024
10053
|
checkOptionalText("collection", metadata.collection);
|
|
10054
|
+
ensure(metadata.collection_id === null || isCollectionId(metadata.collection_id), "collection_id", COLLECTION_ID_RULE);
|
|
10025
10055
|
}
|
|
10026
10056
|
function checkContent(content) {
|
|
10027
10057
|
switch (content?.kind) {
|
|
@@ -10079,6 +10109,7 @@ function arrayCbor(items) {
|
|
|
10079
10109
|
}
|
|
10080
10110
|
return out;
|
|
10081
10111
|
}
|
|
10112
|
+
var optionalHexBytes = (value) => import_CborSerializer.CborSerializer.encodeNullable(value, (hex) => import_CborSerializer.CborSerializer.encodeByteString(import_HexConverter.HexConverter.decode(hex.toLowerCase())));
|
|
10082
10113
|
function metadataCbor(metadata) {
|
|
10083
10114
|
return versioned(
|
|
10084
10115
|
NFT_METADATA_TAG,
|
|
@@ -10088,7 +10119,8 @@ function metadataCbor(metadata) {
|
|
|
10088
10119
|
mediaRefCbor(metadata.animation_url),
|
|
10089
10120
|
optionalText(metadata.external_url),
|
|
10090
10121
|
arrayCbor(metadata.attributes.map(attributeCbor)),
|
|
10091
|
-
optionalText(metadata.collection)
|
|
10122
|
+
optionalText(metadata.collection),
|
|
10123
|
+
optionalHexBytes(metadata.collection_id)
|
|
10092
10124
|
);
|
|
10093
10125
|
}
|
|
10094
10126
|
function encodeNftContent(content) {
|
|
@@ -10146,13 +10178,14 @@ function decodeMedia(body) {
|
|
|
10146
10178
|
const [, mediaType, bytes] = versionedFields(body, MEDIA_ARITY);
|
|
10147
10179
|
return { kind: "media", media_type: decodeText(mediaType), bytes: import_CborDeserializer.CborDeserializer.decodeByteString(bytes) };
|
|
10148
10180
|
}
|
|
10181
|
+
var decodeHex = (item) => import_HexConverter.HexConverter.encode(import_CborDeserializer.CborDeserializer.decodeByteString(item));
|
|
10149
10182
|
function decodeLink(body) {
|
|
10150
10183
|
const [, mediaType, uri, digest] = versionedFields(body, LINK_ARITY);
|
|
10151
10184
|
return {
|
|
10152
10185
|
kind: "link",
|
|
10153
10186
|
media_type: decodeText(mediaType),
|
|
10154
10187
|
uri: decodeText(uri),
|
|
10155
|
-
sha256:
|
|
10188
|
+
sha256: decodeHex(digest)
|
|
10156
10189
|
};
|
|
10157
10190
|
}
|
|
10158
10191
|
function decodeMetadata(body) {
|
|
@@ -10165,7 +10198,8 @@ function decodeMetadata(body) {
|
|
|
10165
10198
|
animation_url: decodeMediaRef("animation_url", fields[4]),
|
|
10166
10199
|
external_url: decodeOptionalText(fields[5]),
|
|
10167
10200
|
attributes: decodeAttributes(fields[6]),
|
|
10168
|
-
collection: decodeOptionalText(fields[7])
|
|
10201
|
+
collection: decodeOptionalText(fields[7]),
|
|
10202
|
+
collection_id: import_CborDeserializer.CborDeserializer.decodeNullable(fields[8], decodeHex)
|
|
10169
10203
|
};
|
|
10170
10204
|
}
|
|
10171
10205
|
var MEDIA_REF_DECODERS = /* @__PURE__ */ new Map([
|
|
@@ -10177,6 +10211,10 @@ var UNSIGNED_DECODERS = /* @__PURE__ */ new Map([
|
|
|
10177
10211
|
[NFT_MEDIA_TAG, decodeMedia],
|
|
10178
10212
|
[NFT_LINK_TAG, decodeLink]
|
|
10179
10213
|
]);
|
|
10214
|
+
var DOCUMENT_DECODERS = /* @__PURE__ */ new Map([
|
|
10215
|
+
[NFT_METADATA_TAG, decodeMetadata],
|
|
10216
|
+
[NFT_MEDIA_TAG, decodeMedia]
|
|
10217
|
+
]);
|
|
10180
10218
|
function decodeBody(decoders, field, tag, body) {
|
|
10181
10219
|
const decode = decoders.get(tag);
|
|
10182
10220
|
if (decode === void 0) throw refuse(field, `tag ${tag} is not allowed here`);
|
|
@@ -10211,20 +10249,35 @@ function parseNftPayload(data) {
|
|
|
10211
10249
|
return null;
|
|
10212
10250
|
}
|
|
10213
10251
|
}
|
|
10214
|
-
function
|
|
10252
|
+
function parseNftDocument(bytes) {
|
|
10253
|
+
try {
|
|
10254
|
+
const document = decodeItem(DOCUMENT_DECODERS, "document", bytes);
|
|
10255
|
+
checkContent(document);
|
|
10256
|
+
return document;
|
|
10257
|
+
} catch {
|
|
10258
|
+
return null;
|
|
10259
|
+
}
|
|
10260
|
+
}
|
|
10261
|
+
function isNftDocumentLink(content) {
|
|
10262
|
+
return content?.kind === "link" && content.media_type === NFT_DOCUMENT_MEDIA_TYPE;
|
|
10263
|
+
}
|
|
10264
|
+
function nftSignedDigest(context, payload) {
|
|
10215
10265
|
const preimage = import_CborSerializer.CborSerializer.encodeArray(
|
|
10216
|
-
import_CborSerializer.CborSerializer.
|
|
10217
|
-
|
|
10218
|
-
|
|
10266
|
+
import_CborSerializer.CborSerializer.encodeByteString(SIGNED_DOMAIN),
|
|
10267
|
+
import_CborSerializer.CborSerializer.encodeUnsignedInteger(NFT_FORMAT_VERSION),
|
|
10268
|
+
import_CborSerializer.CborSerializer.encodeUnsignedInteger(import_NetworkId.NetworkId.fromId(context.networkId).id),
|
|
10269
|
+
import_CborSerializer.CborSerializer.encodeByteString(context.recipientPredicate),
|
|
10270
|
+
import_CborSerializer.CborSerializer.encodeByteString(context.tokenId),
|
|
10271
|
+
import_CborSerializer.CborSerializer.encodeByteString(context.tokenType),
|
|
10219
10272
|
import_CborSerializer.CborSerializer.encodeByteString(payload)
|
|
10220
10273
|
);
|
|
10221
10274
|
return new import_DataHasher.DataHasher(import_HashAlgorithm.HashAlgorithm.SHA256).update(preimage).digest();
|
|
10222
10275
|
}
|
|
10223
|
-
async function verifyNftSignature(signed,
|
|
10276
|
+
async function verifyNftSignature(signed, context) {
|
|
10224
10277
|
try {
|
|
10225
10278
|
if (!import_SigningService.SigningService.isPublicKeyValid(signed.creator)) return "invalid";
|
|
10226
10279
|
const signature = import_Signature.Signature.decode(signed.signature);
|
|
10227
|
-
const digest = await nftSignedDigest(
|
|
10280
|
+
const digest = await nftSignedDigest(context, signed.payload);
|
|
10228
10281
|
return await import_SigningService.SigningService.verifyWithPublicKey(digest, signature, signed.creator) ? "valid" : "invalid";
|
|
10229
10282
|
} catch {
|
|
10230
10283
|
return "invalid";
|
|
@@ -10358,8 +10411,8 @@ function assertMintableData(data) {
|
|
|
10358
10411
|
function nftRecipientCbor(pubkey) {
|
|
10359
10412
|
return import_EncodedPredicate.EncodedPredicate.fromPredicate(import_SignaturePredicate.SignaturePredicate.create(pubkey)).toCBOR();
|
|
10360
10413
|
}
|
|
10361
|
-
async function signPayload(deps, payload,
|
|
10362
|
-
const digest = await nftSignedDigest(
|
|
10414
|
+
async function signPayload(deps, payload, context) {
|
|
10415
|
+
const digest = await nftSignedDigest(context, payload);
|
|
10363
10416
|
const signature = await deps.signingService.sign(digest);
|
|
10364
10417
|
return encodeNftSigned(deps.signingService.publicKey, payload, signature.encode());
|
|
10365
10418
|
}
|
|
@@ -10368,31 +10421,41 @@ async function planNftMint(deps, params) {
|
|
|
10368
10421
|
const tokenType = new import_TokenType.TokenType(params.tokenType).bytes;
|
|
10369
10422
|
const salt = import_TokenSalt.TokenSalt.generate();
|
|
10370
10423
|
const tokenId = await import_TokenId.TokenId.fromSalt(deps.networkId, salt);
|
|
10371
|
-
const data = params.sign ? await signPayload(deps, payload,
|
|
10424
|
+
const data = params.sign ? await signPayload(deps, payload, {
|
|
10425
|
+
networkId: deps.networkId.id,
|
|
10426
|
+
recipientPredicate: nftRecipientCbor(params.recipientPubkey),
|
|
10427
|
+
tokenId: tokenId.bytes,
|
|
10428
|
+
tokenType
|
|
10429
|
+
}) : payload;
|
|
10372
10430
|
assertMintableData(data);
|
|
10373
10431
|
return { data, salt: salt.toBytes(), tokenType, tokenId: import_HexConverter.HexConverter.encode(tokenId.bytes) };
|
|
10374
10432
|
}
|
|
10375
|
-
async function verifyAgainst(signed,
|
|
10433
|
+
async function verifyAgainst(signed, genesisContext) {
|
|
10376
10434
|
try {
|
|
10377
|
-
return await verifyNftSignature(signed,
|
|
10435
|
+
return await verifyNftSignature(signed, genesisContext());
|
|
10378
10436
|
} catch {
|
|
10379
10437
|
return "invalid";
|
|
10380
10438
|
}
|
|
10381
10439
|
}
|
|
10382
|
-
async function readNftData(data,
|
|
10440
|
+
async function readNftData(data, genesisContext) {
|
|
10383
10441
|
const parsed = parseNftPayload(data);
|
|
10384
10442
|
if (parsed === null) return null;
|
|
10385
10443
|
if (parsed.signed === null) return { content: parsed.content, creator: null, signature: "unsigned" };
|
|
10386
10444
|
return {
|
|
10387
10445
|
content: parsed.content,
|
|
10388
10446
|
creator: import_HexConverter.HexConverter.encode(parsed.signed.creator),
|
|
10389
|
-
signature: await verifyAgainst(parsed.signed,
|
|
10447
|
+
signature: await verifyAgainst(parsed.signed, genesisContext)
|
|
10390
10448
|
};
|
|
10391
10449
|
}
|
|
10392
10450
|
async function readTokenNft(token) {
|
|
10393
10451
|
try {
|
|
10394
10452
|
const { genesis } = token.sdkToken;
|
|
10395
|
-
return await readNftData(genesis.data,
|
|
10453
|
+
return await readNftData(genesis.data, () => ({
|
|
10454
|
+
networkId: genesis.networkId.id,
|
|
10455
|
+
recipientPredicate: genesis.recipient.toCBOR(),
|
|
10456
|
+
tokenId: genesis.tokenId.bytes,
|
|
10457
|
+
tokenType: genesis.tokenType.bytes
|
|
10458
|
+
}));
|
|
10396
10459
|
} catch {
|
|
10397
10460
|
return null;
|
|
10398
10461
|
}
|
|
@@ -20853,6 +20916,7 @@ function addressesMatch(a, b) {
|
|
|
20853
20916
|
LIMITS,
|
|
20854
20917
|
MarketModule,
|
|
20855
20918
|
NETWORKS,
|
|
20919
|
+
NFT_DOCUMENT_MEDIA_TYPE,
|
|
20856
20920
|
NFT_LINK_TAG,
|
|
20857
20921
|
NFT_MAX_PAYLOAD_BYTES,
|
|
20858
20922
|
NFT_MEDIA_TAG,
|
|
@@ -20931,6 +20995,7 @@ function addressesMatch(a, b) {
|
|
|
20931
20995
|
identityFromMnemonicSync,
|
|
20932
20996
|
initSphere,
|
|
20933
20997
|
isKnownToken,
|
|
20998
|
+
isNftDocumentLink,
|
|
20934
20999
|
isPhoneNumber,
|
|
20935
21000
|
isPossiblyCommittedSendOutcome,
|
|
20936
21001
|
isSphereError,
|
|
@@ -20948,6 +21013,7 @@ function addressesMatch(a, b) {
|
|
|
20948
21013
|
normalizeNametag,
|
|
20949
21014
|
parseAddress,
|
|
20950
21015
|
parseAndDecryptWalletText,
|
|
21016
|
+
parseNftDocument,
|
|
20951
21017
|
parseNftPayload,
|
|
20952
21018
|
parseTokenAmount,
|
|
20953
21019
|
parseWalletText,
|