@unicitylabs/sphere-sdk 0.17.2-dev.1 → 0.17.2-dev.3

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.
Files changed (47) hide show
  1. package/dist/connect/index.cjs +202 -8
  2. package/dist/connect/index.cjs.map +1 -1
  3. package/dist/connect/index.d.cts +81 -4
  4. package/dist/connect/index.d.ts +81 -4
  5. package/dist/connect/index.js +202 -8
  6. package/dist/connect/index.js.map +1 -1
  7. package/dist/core/index.cjs +48 -21
  8. package/dist/core/index.cjs.map +1 -1
  9. package/dist/core/index.d.cts +2 -0
  10. package/dist/core/index.d.ts +2 -0
  11. package/dist/core/index.js +48 -21
  12. package/dist/core/index.js.map +1 -1
  13. package/dist/impl/browser/connect/index.cjs +17 -5
  14. package/dist/impl/browser/connect/index.cjs.map +1 -1
  15. package/dist/impl/browser/connect/index.d.cts +3 -1
  16. package/dist/impl/browser/connect/index.d.ts +3 -1
  17. package/dist/impl/browser/connect/index.js +17 -5
  18. package/dist/impl/browser/connect/index.js.map +1 -1
  19. package/dist/impl/nodejs/connect/index.cjs +16 -4
  20. package/dist/impl/nodejs/connect/index.cjs.map +1 -1
  21. package/dist/impl/nodejs/connect/index.d.cts +1 -1
  22. package/dist/impl/nodejs/connect/index.d.ts +1 -1
  23. package/dist/impl/nodejs/connect/index.js +16 -4
  24. package/dist/impl/nodejs/connect/index.js.map +1 -1
  25. package/dist/impl/wallet-api-v2/index.cjs +3 -0
  26. package/dist/impl/wallet-api-v2/index.cjs.map +1 -1
  27. package/dist/impl/wallet-api-v2/index.js +3 -0
  28. package/dist/impl/wallet-api-v2/index.js.map +1 -1
  29. package/dist/index.cjs +67 -21
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +22 -1
  32. package/dist/index.d.ts +22 -1
  33. package/dist/index.js +64 -21
  34. package/dist/index.js.map +1 -1
  35. package/dist/modules/payments-v2/index.cjs +40 -6
  36. package/dist/modules/payments-v2/index.cjs.map +1 -1
  37. package/dist/modules/payments-v2/index.d.cts +22 -1
  38. package/dist/modules/payments-v2/index.d.ts +22 -1
  39. package/dist/modules/payments-v2/index.js +37 -6
  40. package/dist/modules/payments-v2/index.js.map +1 -1
  41. package/dist/token-engine/index.cjs +67 -21
  42. package/dist/token-engine/index.cjs.map +1 -1
  43. package/dist/token-engine/index.d.cts +28 -4
  44. package/dist/token-engine/index.d.ts +28 -4
  45. package/dist/token-engine/index.js +64 -21
  46. package/dist/token-engine/index.js.map +1 -1
  47. package/package.json +1 -1
@@ -43,6 +43,8 @@ __export(connect_exports, {
43
43
  hasMethodPermission: () => hasMethodPermission,
44
44
  isAutoPushedEvent: () => isAutoPushedEvent,
45
45
  isSphereConnectMessage: () => isSphereConnectMessage,
46
+ nftContentFromWire: () => nftContentFromWire,
47
+ nftContentToWire: () => nftContentToWire,
46
48
  validatePermissions: () => validatePermissions
47
49
  });
48
50
  module.exports = __toCommonJS(connect_exports);
@@ -291,7 +293,7 @@ var HOST_READY_TIMEOUT = 3e4;
291
293
 
292
294
  // connect/protocol.ts
293
295
  var SPHERE_CONNECT_NAMESPACE = "sphere-connect";
294
- var SPHERE_CONNECT_VERSION = "2.2";
296
+ var SPHERE_CONNECT_VERSION = "2.3";
295
297
  var DEFAULT_MIN_CLIENT_SDK_VERSION = "0.14.1-0";
296
298
  var RPC_METHODS = {
297
299
  GET_IDENTITY: "sphere_getIdentity",
@@ -318,7 +320,9 @@ var INTENT_ACTIONS = {
318
320
  MINT: "mint",
319
321
  // #777: params { to, tokenId, memo? }. Named NFT rather than 'send_token':
320
322
  // coins are tokens too, so 'token' does not say which kind moves.
321
- SEND_NFT: "send_nft"
323
+ SEND_NFT: "send_nft",
324
+ // Connect 2.3: params MintNftIntentParams, result MintNftIntentResult (connect/nft-wire.ts).
325
+ MINT_NFT: "mint_nft"
322
326
  };
323
327
  var ERROR_CODES = {
324
328
  // Standard JSON-RPC
@@ -452,7 +456,7 @@ function checkCompatibility(input) {
452
456
  }
453
457
 
454
458
  // connect/version.ts
455
- var SDK_VERSION = "0.17.2-dev.1";
459
+ var SDK_VERSION = "0.17.2-dev.3";
456
460
 
457
461
  // connect/permissions.ts
458
462
  var PERMISSION_SCOPES = {
@@ -470,7 +474,9 @@ var PERMISSION_SCOPES = {
470
474
  SIGN_REQUEST: "sign:request",
471
475
  MINT_REQUEST: "mint:request",
472
476
  /** #777: moving a coinless token (an NFT). Distinct from transfer:request. */
473
- NFT_TRANSFER: "nft:transfer"
477
+ NFT_TRANSFER: "nft:transfer",
478
+ /** Minting an NFT signs dApp-chosen content as the user; mint:request and nft:transfer do not imply it. */
479
+ NFT_MINT: "nft:mint"
474
480
  };
475
481
  var ALL_PERMISSIONS = Object.values(PERMISSION_SCOPES);
476
482
  var DEFAULT_PERMISSIONS = [
@@ -498,7 +504,8 @@ var INTENT_PERMISSIONS = {
498
504
  [INTENT_ACTIONS.RECEIVE]: PERMISSION_SCOPES.IDENTITY_READ,
499
505
  [INTENT_ACTIONS.SIGN_MESSAGE]: PERMISSION_SCOPES.SIGN_REQUEST,
500
506
  [INTENT_ACTIONS.MINT]: PERMISSION_SCOPES.MINT_REQUEST,
501
- [INTENT_ACTIONS.SEND_NFT]: PERMISSION_SCOPES.NFT_TRANSFER
507
+ [INTENT_ACTIONS.SEND_NFT]: PERMISSION_SCOPES.NFT_TRANSFER,
508
+ [INTENT_ACTIONS.MINT_NFT]: PERMISSION_SCOPES.NFT_MINT
502
509
  };
503
510
  function hasMethodPermission(granted, method) {
504
511
  const required = METHOD_PERMISSIONS[method];
@@ -778,6 +785,7 @@ var CHANNEL_ONLY_CODES = /* @__PURE__ */ new Set([
778
785
  ERROR_CODES.WALLET_LOCKED,
779
786
  ERROR_CODES.NOT_CONNECTED
780
787
  ]);
788
+ var ALWAYS_ASK_INTENTS = /* @__PURE__ */ new Set([INTENT_ACTIONS.MINT_NFT]);
781
789
  var DEFAULT_REQUEST_DEADLINE_MS = 25e3;
782
790
  var DEFAULT_INTENT_DEADLINE_MS = 18e4;
783
791
  var DEFAULT_HANDSHAKE_DEADLINE_MS = 12e4;
@@ -863,8 +871,11 @@ var ConnectHost = class {
863
871
  getSession() {
864
872
  return this.session;
865
873
  }
866
- /** Register an auto-approve handler for an intent action (session-scoped). */
874
+ /** Register an auto-approve handler for an intent action (session-scoped). Throws for an intent that always asks the user. */
867
875
  setIntentAutoApprove(action, handler) {
876
+ if (ALWAYS_ASK_INTENTS.has(action)) {
877
+ throw new SphereError(`Intent ${action} always asks the user and cannot be auto-approved`, "INVALID_CONFIG");
878
+ }
868
879
  this.autoApprovedIntents.set(action, handler);
869
880
  }
870
881
  /** Remove auto-approve for an intent action. */
@@ -1353,7 +1364,7 @@ var ConnectHost = class {
1353
1364
  signal: entry.controller.signal
1354
1365
  };
1355
1366
  try {
1356
- const autoHandler = this.autoApprovedIntents.get(msg.action);
1367
+ const autoHandler = ALWAYS_ASK_INTENTS.has(msg.action) ? void 0 : this.autoApprovedIntents.get(msg.action);
1357
1368
  const response = autoHandler ? await autoHandler(msg.action, msg.params, session) : await this.config.onIntent(msg.action, msg.params, session, ctx);
1358
1369
  if (!this.inFlight.settle(msg.id)) return;
1359
1370
  if (response.error) {
@@ -1367,7 +1378,8 @@ var ConnectHost = class {
1367
1378
  this.sendIntentError(
1368
1379
  msg.id,
1369
1380
  asserts ? ERROR_CODES.INTENT_OUTCOME_UNKNOWN : response.error.code,
1370
- asserts ? INTENT_UNKNOWN_MESSAGE : response.error.message
1381
+ asserts ? INTENT_UNKNOWN_MESSAGE : response.error.message,
1382
+ asserts ? void 0 : response.error.data
1371
1383
  );
1372
1384
  } else {
1373
1385
  this.sendIntentResult(msg.id, response.result);
@@ -2050,4 +2062,186 @@ var ConnectClient = class {
2050
2062
  this.locked = false;
2051
2063
  }
2052
2064
  };
2065
+
2066
+ // core/base64.ts
2067
+ var ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2068
+ var INVALID = 255;
2069
+ var SEXTETS = new Uint8Array(128).fill(INVALID);
2070
+ for (let i = 0; i < ALPHABET.length; i++) SEXTETS[ALPHABET.charCodeAt(i)] = i;
2071
+ function base64Encode(bytes) {
2072
+ let out = "";
2073
+ for (let i = 0; i < bytes.length; i += 3) {
2074
+ const b1 = i + 1 < bytes.length ? bytes[i + 1] : 0;
2075
+ const b2 = i + 2 < bytes.length ? bytes[i + 2] : 0;
2076
+ const triple = bytes[i] << 16 | b1 << 8 | b2;
2077
+ out += ALPHABET[triple >> 18] + ALPHABET[triple >> 12 & 63];
2078
+ out += i + 1 < bytes.length ? ALPHABET[triple >> 6 & 63] : "=";
2079
+ out += i + 2 < bytes.length ? ALPHABET[triple & 63] : "=";
2080
+ }
2081
+ return out;
2082
+ }
2083
+ function base64DecodeCanonical(text) {
2084
+ if (text.length % 4 !== 0) return null;
2085
+ const padding = text.endsWith("==") ? 2 : text.endsWith("=") ? 1 : 0;
2086
+ const out = new Uint8Array(text.length / 4 * 3 - padding);
2087
+ let buffer = 0;
2088
+ let bits = 0;
2089
+ let offset = 0;
2090
+ for (let i = 0; i < text.length - padding; i++) {
2091
+ const code = text.charCodeAt(i);
2092
+ const sextet = code < SEXTETS.length ? SEXTETS[code] : INVALID;
2093
+ if (sextet === INVALID) return null;
2094
+ buffer = (buffer << 6 | sextet) & 4095;
2095
+ bits += 6;
2096
+ if (bits >= 8) {
2097
+ bits -= 8;
2098
+ out[offset++] = buffer >> bits;
2099
+ }
2100
+ }
2101
+ return (buffer & (1 << bits) - 1) === 0 ? out : null;
2102
+ }
2103
+
2104
+ // connect/nft-wire.ts
2105
+ var METADATA_FIELDS = [
2106
+ "kind",
2107
+ "name",
2108
+ "description",
2109
+ "image",
2110
+ "animation_url",
2111
+ "external_url",
2112
+ "attributes",
2113
+ "collection",
2114
+ "collection_id"
2115
+ ];
2116
+ var MEDIA_FIELDS = ["kind", "media_type", "bytes"];
2117
+ var LINK_FIELDS = ["kind", "media_type", "uri", "sha256"];
2118
+ var ATTRIBUTE_FIELDS = ["trait_type", "value"];
2119
+ var CONTENT_KINDS = "must be 'metadata', 'media' or 'link'";
2120
+ var MEDIA_REF_KINDS = "must be 'media' or 'link'";
2121
+ function refuse(field, rule) {
2122
+ return new SphereError(`Invalid NFT ${field}: ${rule}`, "VALIDATION_ERROR");
2123
+ }
2124
+ function mediaToWire(media, field) {
2125
+ if (!(media.bytes instanceof Uint8Array)) throw refuse(`${field}.bytes`, "must be a Uint8Array");
2126
+ return { kind: "media", media_type: media.media_type, bytes: base64Encode(media.bytes) };
2127
+ }
2128
+ function linkToWire(link) {
2129
+ return { kind: "link", media_type: link.media_type, uri: link.uri, sha256: link.sha256 };
2130
+ }
2131
+ function mediaRefToWire(ref, field) {
2132
+ if (ref === null) return null;
2133
+ if (ref?.kind === "media") return mediaToWire(ref, field);
2134
+ if (ref?.kind === "link") return linkToWire(ref);
2135
+ throw refuse(`${field}.kind`, MEDIA_REF_KINDS);
2136
+ }
2137
+ function metadataToWire(metadata) {
2138
+ return {
2139
+ kind: "metadata",
2140
+ name: metadata.name,
2141
+ description: metadata.description,
2142
+ image: mediaRefToWire(metadata.image, "content.image"),
2143
+ animation_url: mediaRefToWire(metadata.animation_url, "content.animation_url"),
2144
+ external_url: metadata.external_url,
2145
+ attributes: metadata.attributes.map(({ trait_type, value }) => ({ trait_type, value })),
2146
+ collection: metadata.collection,
2147
+ collection_id: metadata.collection_id
2148
+ };
2149
+ }
2150
+ function nftContentToWire(content) {
2151
+ switch (content?.kind) {
2152
+ case "metadata":
2153
+ return metadataToWire(content);
2154
+ case "media":
2155
+ return mediaToWire(content, "content");
2156
+ case "link":
2157
+ return linkToWire(content);
2158
+ default:
2159
+ throw refuse("content.kind", CONTENT_KINDS);
2160
+ }
2161
+ }
2162
+ function recordAt(value, field, rule = "must be an object") {
2163
+ if (typeof value !== "object" || value === null || Array.isArray(value)) throw refuse(field, rule);
2164
+ return value;
2165
+ }
2166
+ function requireExactFields(record, field, fields) {
2167
+ const missing = fields.find((name) => !Object.prototype.hasOwnProperty.call(record, name));
2168
+ if (missing !== void 0) throw refuse(`${field}.${missing}`, "is missing \u2014 an absent optional field is null");
2169
+ const extra = Object.keys(record).find((name) => !fields.includes(name));
2170
+ if (extra !== void 0) throw refuse(`${field}.${extra}`, "is not a field of this item");
2171
+ }
2172
+ function stringAt(record, field, name) {
2173
+ const value = record[name];
2174
+ if (typeof value !== "string") throw refuse(`${field}.${name}`, "must be a string");
2175
+ return value;
2176
+ }
2177
+ function optionalStringAt(record, field, name) {
2178
+ const value = record[name];
2179
+ if (value === null) return null;
2180
+ if (typeof value !== "string") throw refuse(`${field}.${name}`, "must be a string or null");
2181
+ return value;
2182
+ }
2183
+ function mediaFromWire(record, field) {
2184
+ requireExactFields(record, field, MEDIA_FIELDS);
2185
+ const mediaType = stringAt(record, field, "media_type");
2186
+ const bytes = base64DecodeCanonical(stringAt(record, field, "bytes"));
2187
+ if (bytes === null) throw refuse(`${field}.bytes`, "must be canonical standard base64 with padding (RFC 4648 \xA74)");
2188
+ return { kind: "media", media_type: mediaType, bytes };
2189
+ }
2190
+ function linkFromWire(record, field) {
2191
+ requireExactFields(record, field, LINK_FIELDS);
2192
+ return {
2193
+ kind: "link",
2194
+ media_type: stringAt(record, field, "media_type"),
2195
+ uri: stringAt(record, field, "uri"),
2196
+ sha256: stringAt(record, field, "sha256")
2197
+ };
2198
+ }
2199
+ function mediaRefFromWire(value, field) {
2200
+ if (value === null) return null;
2201
+ const record = recordAt(value, field, "must be a media or link object, or null");
2202
+ if (record.kind === "media") return mediaFromWire(record, field);
2203
+ if (record.kind === "link") return linkFromWire(record, field);
2204
+ throw refuse(`${field}.kind`, MEDIA_REF_KINDS);
2205
+ }
2206
+ function attributeFromWire(value, field) {
2207
+ const record = recordAt(value, field);
2208
+ requireExactFields(record, field, ATTRIBUTE_FIELDS);
2209
+ const traitType = stringAt(record, field, "trait_type");
2210
+ const attributeValue = record.value;
2211
+ if (typeof attributeValue !== "string" && typeof attributeValue !== "number") {
2212
+ throw refuse(`${field}.value`, "must be a string or a number");
2213
+ }
2214
+ return { trait_type: traitType, value: attributeValue };
2215
+ }
2216
+ function attributesFromWire(value, field) {
2217
+ if (!Array.isArray(value)) throw refuse(field, "must be an array \u2014 [] when there are none");
2218
+ return Array.from(value, (entry, index) => attributeFromWire(entry, `${field}[${index}]`));
2219
+ }
2220
+ function metadataFromWire(record) {
2221
+ requireExactFields(record, "content", METADATA_FIELDS);
2222
+ return {
2223
+ kind: "metadata",
2224
+ name: stringAt(record, "content", "name"),
2225
+ description: optionalStringAt(record, "content", "description"),
2226
+ image: mediaRefFromWire(record.image, "content.image"),
2227
+ animation_url: mediaRefFromWire(record.animation_url, "content.animation_url"),
2228
+ external_url: optionalStringAt(record, "content", "external_url"),
2229
+ attributes: attributesFromWire(record.attributes, "content.attributes"),
2230
+ collection: optionalStringAt(record, "content", "collection"),
2231
+ collection_id: optionalStringAt(record, "content", "collection_id")
2232
+ };
2233
+ }
2234
+ function nftContentFromWire(wire) {
2235
+ const record = recordAt(wire, "content");
2236
+ switch (record.kind) {
2237
+ case "metadata":
2238
+ return metadataFromWire(record);
2239
+ case "media":
2240
+ return mediaFromWire(record, "content");
2241
+ case "link":
2242
+ return linkFromWire(record, "content");
2243
+ default:
2244
+ throw refuse("content.kind", CONTENT_KINDS);
2245
+ }
2246
+ }
2053
2247
  //# sourceMappingURL=index.cjs.map