FRE-600: Fix code review blockers

- Consolidated duplicate UndoManagers to single instance
- Fixed connection promise to only resolve on 'connected' status
- Fixed WebSocketProvider import (WebsocketProvider)
- Added proper doc.destroy() cleanup
- Renamed isPresenceInitialized property to avoid conflict

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
2026-04-25 00:08:01 -04:00
parent 65b552bb08
commit 7c684a42cc
48450 changed files with 5679671 additions and 383 deletions

View File

@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCommitment = getCommitment;
/**
* TODO: docs
*/
function getCommitment(commitment) {
switch (commitment) {
case 'processed':
case 'confirmed':
case 'finalized':
case undefined:
return commitment;
case 'recent':
return 'processed';
case 'single':
case 'singleGossip':
return 'confirmed';
case 'max':
case 'root':
return 'finalized';
default:
return undefined;
}
}
//# sourceMappingURL=commitment.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"commitment.js","sourceRoot":"","sources":["../../src/commitment.ts"],"names":[],"mappings":";;AAQA,sCAkBC;AArBD;;GAEG;AACH,SAAgB,aAAa,CAAC,UAAuB;IACjD,QAAQ,UAAU,EAAE,CAAC;QACjB,KAAK,WAAW,CAAC;QACjB,KAAK,WAAW,CAAC;QACjB,KAAK,WAAW,CAAC;QACjB,KAAK,SAAS;YACV,OAAO,UAAU,CAAC;QACtB,KAAK,QAAQ;YACT,OAAO,WAAW,CAAC;QACvB,KAAK,QAAQ,CAAC;QACd,KAAK,cAAc;YACf,OAAO,WAAW,CAAC;QACvB,KAAK,KAAK,CAAC;QACX,KAAK,MAAM;YACP,OAAO,WAAW,CAAC;QACvB;YACI,OAAO,SAAS,CAAC;IACzB,CAAC;AACL,CAAC"}

View File

@@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LOCALNET_ENDPOINT = exports.TESTNET_ENDPOINT = exports.DEVNET_ENDPOINT = exports.MAINNET_ENDPOINT = void 0;
exports.getChainForEndpoint = getChainForEndpoint;
exports.getEndpointForChain = getEndpointForChain;
const wallet_standard_chains_1 = require("@solana/wallet-standard-chains");
/** TODO: docs */
exports.MAINNET_ENDPOINT = 'https://api.mainnet-beta.solana.com';
/** TODO: docs */
exports.DEVNET_ENDPOINT = 'https://api.devnet.solana.com';
/** TODO: docs */
exports.TESTNET_ENDPOINT = 'https://api.testnet.solana.com';
/** TODO: docs */
exports.LOCALNET_ENDPOINT = 'http://localhost:8899';
/**
* TODO: docs
*/
function getChainForEndpoint(endpoint) {
if (endpoint.includes(exports.MAINNET_ENDPOINT))
return wallet_standard_chains_1.SOLANA_MAINNET_CHAIN;
if (/\bdevnet\b/i.test(endpoint))
return wallet_standard_chains_1.SOLANA_DEVNET_CHAIN;
if (/\btestnet\b/i.test(endpoint))
return wallet_standard_chains_1.SOLANA_TESTNET_CHAIN;
if (/\blocalhost\b/i.test(endpoint) || /\b127\.0\.0\.1\b/.test(endpoint))
return wallet_standard_chains_1.SOLANA_LOCALNET_CHAIN;
return wallet_standard_chains_1.SOLANA_MAINNET_CHAIN;
}
/**
* TODO: docs
*/
function getEndpointForChain(chain, endpoint) {
if (endpoint)
return endpoint;
if (chain === wallet_standard_chains_1.SOLANA_MAINNET_CHAIN)
return exports.MAINNET_ENDPOINT;
if (chain === wallet_standard_chains_1.SOLANA_DEVNET_CHAIN)
return exports.DEVNET_ENDPOINT;
if (chain === wallet_standard_chains_1.SOLANA_TESTNET_CHAIN)
return exports.TESTNET_ENDPOINT;
if (chain === wallet_standard_chains_1.SOLANA_LOCALNET_CHAIN)
return exports.LOCALNET_ENDPOINT;
return exports.MAINNET_ENDPOINT;
}
//# sourceMappingURL=endpoint.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"endpoint.js","sourceRoot":"","sources":["../../src/endpoint.ts"],"names":[],"mappings":";;;AAoBA,kDAMC;AAKD,kDAOC;AArCD,2EAKwC;AAExC,iBAAiB;AACJ,QAAA,gBAAgB,GAAG,qCAAqC,CAAC;AACtE,iBAAiB;AACJ,QAAA,eAAe,GAAG,+BAA+B,CAAC;AAC/D,iBAAiB;AACJ,QAAA,gBAAgB,GAAG,gCAAgC,CAAC;AACjE,iBAAiB;AACJ,QAAA,iBAAiB,GAAG,uBAAuB,CAAC;AAEzD;;GAEG;AACH,SAAgB,mBAAmB,CAAC,QAAgB;IAChD,IAAI,QAAQ,CAAC,QAAQ,CAAC,wBAAgB,CAAC;QAAE,OAAO,6CAAoB,CAAC;IACrE,IAAI,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,4CAAmB,CAAC;IAC7D,IAAI,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,6CAAoB,CAAC;IAC/D,IAAI,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,8CAAqB,CAAC;IACvG,OAAO,6CAAoB,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,SAAgB,mBAAmB,CAAC,KAAkB,EAAE,QAAiB;IACrE,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,IAAI,KAAK,KAAK,6CAAoB;QAAE,OAAO,wBAAgB,CAAC;IAC5D,IAAI,KAAK,KAAK,4CAAmB;QAAE,OAAO,uBAAe,CAAC;IAC1D,IAAI,KAAK,KAAK,6CAAoB;QAAE,OAAO,wBAAgB,CAAC;IAC5D,IAAI,KAAK,KAAK,8CAAqB;QAAE,OAAO,yBAAiB,CAAC;IAC9D,OAAO,wBAAgB,CAAC;AAC5B,CAAC"}

View File

@@ -0,0 +1,21 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./commitment.js"), exports);
__exportStar(require("./endpoint.js"), exports);
__exportStar(require("./signIn.js"), exports);
__exportStar(require("./signMessage.js"), exports);
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC;AAChC,gDAA8B;AAC9B,8CAA4B;AAC5B,mDAAiC"}

View File

@@ -0,0 +1 @@
{ "type": "commonjs" }

View File

@@ -0,0 +1,186 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.verifySignIn = verifySignIn;
exports.deriveSignInMessage = deriveSignInMessage;
exports.deriveSignInMessageText = deriveSignInMessageText;
exports.parseSignInMessage = parseSignInMessage;
exports.parseSignInMessageText = parseSignInMessageText;
exports.createSignInMessage = createSignInMessage;
exports.createSignInMessageText = createSignInMessageText;
const signMessage_js_1 = require("./signMessage.js");
const util_js_1 = require("./util.js");
/**
* TODO: docs
*/
function verifySignIn(input, output) {
const { signedMessage, signature, account: { publicKey }, } = output;
const message = deriveSignInMessage(input, output);
return (!!message && (0, signMessage_js_1.verifyMessageSignature)({ message, signedMessage, signature, publicKey: publicKey }));
}
/**
* TODO: docs
*/
function deriveSignInMessage(input, output) {
const text = deriveSignInMessageText(input, output);
if (!text)
return null;
return new TextEncoder().encode(text);
}
/**
* TODO: docs
*/
function deriveSignInMessageText(input, output) {
const parsed = parseSignInMessage(output.signedMessage);
if (!parsed)
return null;
if (input.domain && input.domain !== parsed.domain)
return null;
if (input.address && input.address !== parsed.address)
return null;
if (input.statement !== parsed.statement)
return null;
if (input.uri !== parsed.uri)
return null;
if (input.version !== parsed.version)
return null;
if (input.chainId !== parsed.chainId)
return null;
if (input.nonce !== parsed.nonce)
return null;
if (input.issuedAt !== parsed.issuedAt)
return null;
if (input.expirationTime !== parsed.expirationTime)
return null;
if (input.notBefore !== parsed.notBefore)
return null;
if (input.requestId !== parsed.requestId)
return null;
if (input.resources) {
if (!parsed.resources)
return null;
if (!(0, util_js_1.arraysEqual)(input.resources, parsed.resources))
return null;
}
else if (parsed.resources)
return null;
return createSignInMessageText(parsed);
}
/**
* TODO: docs
*/
function parseSignInMessage(message) {
const text = new TextDecoder().decode(message);
return parseSignInMessageText(text);
}
// TODO: implement https://github.com/solana-labs/solana/blob/master/docs/src/proposals/off-chain-message-signing.md
const DOMAIN = '(?<domain>[^\\n]+?) wants you to sign in with your Solana account:\\n';
const ADDRESS = '(?<address>[^\\n]+)(?:\\n|$)';
const STATEMENT = '(?:\\n(?<statement>[\\S\\s]*?)(?:\\n|$))??';
const URI = '(?:\\nURI: (?<uri>[^\\n]+))?';
const VERSION = '(?:\\nVersion: (?<version>[^\\n]+))?';
const CHAIN_ID = '(?:\\nChain ID: (?<chainId>[^\\n]+))?';
const NONCE = '(?:\\nNonce: (?<nonce>[^\\n]+))?';
const ISSUED_AT = '(?:\\nIssued At: (?<issuedAt>[^\\n]+))?';
const EXPIRATION_TIME = '(?:\\nExpiration Time: (?<expirationTime>[^\\n]+))?';
const NOT_BEFORE = '(?:\\nNot Before: (?<notBefore>[^\\n]+))?';
const REQUEST_ID = '(?:\\nRequest ID: (?<requestId>[^\\n]+))?';
const RESOURCES = '(?:\\nResources:(?<resources>(?:\\n- [^\\n]+)*))?';
const FIELDS = `${URI}${VERSION}${CHAIN_ID}${NONCE}${ISSUED_AT}${EXPIRATION_TIME}${NOT_BEFORE}${REQUEST_ID}${RESOURCES}`;
const MESSAGE = new RegExp(`^${DOMAIN}${ADDRESS}${STATEMENT}${FIELDS}\\n*$`);
/**
* TODO: docs
*/
function parseSignInMessageText(text) {
var _a;
const match = MESSAGE.exec(text);
if (!match)
return null;
const groups = match.groups;
if (!groups)
return null;
return {
domain: groups.domain,
address: groups.address,
statement: groups.statement,
uri: groups.uri,
version: groups.version,
nonce: groups.nonce,
chainId: groups.chainId,
issuedAt: groups.issuedAt,
expirationTime: groups.expirationTime,
notBefore: groups.notBefore,
requestId: groups.requestId,
resources: (_a = groups.resources) === null || _a === void 0 ? void 0 : _a.split('\n- ').slice(1),
};
}
/**
* TODO: docs
*/
function createSignInMessage(input) {
const text = createSignInMessageText(input);
return new TextEncoder().encode(text);
}
/**
* TODO: docs
*/
function createSignInMessageText(input) {
// ${domain} wants you to sign in with your Solana account:
// ${address}
//
// ${statement}
//
// URI: ${uri}
// Version: ${version}
// Chain ID: ${chain}
// Nonce: ${nonce}
// Issued At: ${issued-at}
// Expiration Time: ${expiration-time}
// Not Before: ${not-before}
// Request ID: ${request-id}
// Resources:
// - ${resources[0]}
// - ${resources[1]}
// ...
// - ${resources[n]}
let message = `${input.domain} wants you to sign in with your Solana account:\n`;
message += `${input.address}`;
if (input.statement) {
message += `\n\n${input.statement}`;
}
const fields = [];
if (input.uri) {
fields.push(`URI: ${input.uri}`);
}
if (input.version) {
fields.push(`Version: ${input.version}`);
}
if (input.chainId) {
fields.push(`Chain ID: ${input.chainId}`);
}
if (input.nonce) {
fields.push(`Nonce: ${input.nonce}`);
}
if (input.issuedAt) {
fields.push(`Issued At: ${input.issuedAt}`);
}
if (input.expirationTime) {
fields.push(`Expiration Time: ${input.expirationTime}`);
}
if (input.notBefore) {
fields.push(`Not Before: ${input.notBefore}`);
}
if (input.requestId) {
fields.push(`Request ID: ${input.requestId}`);
}
if (input.resources) {
fields.push(`Resources:`);
for (const resource of input.resources) {
fields.push(`- ${resource}`);
}
}
if (fields.length) {
message += `\n\n${fields.join('\n')}`;
}
return message;
}
//# sourceMappingURL=signIn.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.verifyMessageSignature = verifyMessageSignature;
exports.verifySignMessage = verifySignMessage;
const ed25519_1 = require("@noble/curves/ed25519");
const util_js_1 = require("./util.js");
/**
* TODO: docs
*/
function verifyMessageSignature({ message, signedMessage, signature, publicKey, }) {
// TODO: implement https://github.com/solana-labs/solana/blob/master/docs/src/proposals/off-chain-message-signing.md
return (0, util_js_1.bytesEqual)(message, signedMessage) && ed25519_1.ed25519.verify(signature, signedMessage, publicKey);
}
/**
* TODO: docs
*/
function verifySignMessage(input, output) {
const { message, account: { publicKey }, } = input;
const { signedMessage, signature } = output;
return verifyMessageSignature({ message, signedMessage, signature, publicKey: publicKey });
}
//# sourceMappingURL=signMessage.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"signMessage.js","sourceRoot":"","sources":["../../src/signMessage.ts"],"names":[],"mappings":";;AAOA,wDAaC;AAKD,8CAOC;AAhCD,mDAAgD;AAEhD,uCAAuC;AAEvC;;GAEG;AACH,SAAgB,sBAAsB,CAAC,EACnC,OAAO,EACP,aAAa,EACb,SAAS,EACT,SAAS,GAMZ;IACG,oHAAoH;IACpH,OAAO,IAAA,oBAAU,EAAC,OAAO,EAAE,aAAa,CAAC,IAAI,iBAAO,CAAC,MAAM,CAAC,SAAS,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;AACrG,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB,CAAC,KAA6B,EAAE,MAA+B;IAC5F,MAAM,EACF,OAAO,EACP,OAAO,EAAE,EAAE,SAAS,EAAE,GACzB,GAAG,KAAK,CAAC;IACV,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAC5C,OAAO,sBAAsB,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,SAAuB,EAAE,CAAC,CAAC;AAC7G,CAAC"}

View File

@@ -0,0 +1 @@
{"root":["../../src/commitment.ts","../../src/endpoint.ts","../../src/index.ts","../../src/signIn.ts","../../src/signMessage.ts","../../src/util.ts"],"version":"5.7.3"}

View File

@@ -0,0 +1,44 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.arraysEqual = arraysEqual;
exports.bytesEqual = bytesEqual;
/**
* @internal
*
* Efficiently compare {@link Indexed} arrays (e.g. `Array` and `Uint8Array`).
*
* @param a An array.
* @param b Another array.
*
* @return `true` if the arrays have the same length and elements, `false` otherwise.
*
* @group Internal
*/
function arraysEqual(a, b) {
if (a === b)
return true;
const length = a.length;
if (length !== b.length)
return false;
for (let i = 0; i < length; i++) {
if (a[i] !== b[i])
return false;
}
return true;
}
/**
* @internal
*
* Efficiently compare byte arrays, using {@link arraysEqual}.
*
* @param a A byte array.
* @param b Another byte array.
*
* @return `true` if the byte arrays have the same length and bytes, `false` otherwise.
*
* @group Internal
*/
function bytesEqual(a, b) {
return arraysEqual(a, b);
}
//# sourceMappingURL=util.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/util.ts"],"names":[],"mappings":";;AA0BA,kCAWC;AAcD,gCAEC;AAvCD;;;;;;;;;;;GAWG;AACH,SAAgB,WAAW,CAAI,CAAa,EAAE,CAAa;IACvD,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzB,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IACxB,IAAI,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAEtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9B,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;IACpC,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,UAAU,CAAC,CAAa,EAAE,CAAa;IACnD,OAAO,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC7B,CAAC"}

View File

@@ -0,0 +1,23 @@
/**
* TODO: docs
*/
export function getCommitment(commitment) {
switch (commitment) {
case 'processed':
case 'confirmed':
case 'finalized':
case undefined:
return commitment;
case 'recent':
return 'processed';
case 'single':
case 'singleGossip':
return 'confirmed';
case 'max':
case 'root':
return 'finalized';
default:
return undefined;
}
}
//# sourceMappingURL=commitment.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"commitment.js","sourceRoot":"","sources":["../../src/commitment.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,UAAuB;IACjD,QAAQ,UAAU,EAAE,CAAC;QACjB,KAAK,WAAW,CAAC;QACjB,KAAK,WAAW,CAAC;QACjB,KAAK,WAAW,CAAC;QACjB,KAAK,SAAS;YACV,OAAO,UAAU,CAAC;QACtB,KAAK,QAAQ;YACT,OAAO,WAAW,CAAC;QACvB,KAAK,QAAQ,CAAC;QACd,KAAK,cAAc;YACf,OAAO,WAAW,CAAC;QACvB,KAAK,KAAK,CAAC;QACX,KAAK,MAAM;YACP,OAAO,WAAW,CAAC;QACvB;YACI,OAAO,SAAS,CAAC;IACzB,CAAC;AACL,CAAC"}

View File

@@ -0,0 +1,40 @@
import { SOLANA_DEVNET_CHAIN, SOLANA_LOCALNET_CHAIN, SOLANA_MAINNET_CHAIN, SOLANA_TESTNET_CHAIN, } from '@solana/wallet-standard-chains';
/** TODO: docs */
export const MAINNET_ENDPOINT = 'https://api.mainnet-beta.solana.com';
/** TODO: docs */
export const DEVNET_ENDPOINT = 'https://api.devnet.solana.com';
/** TODO: docs */
export const TESTNET_ENDPOINT = 'https://api.testnet.solana.com';
/** TODO: docs */
export const LOCALNET_ENDPOINT = 'http://localhost:8899';
/**
* TODO: docs
*/
export function getChainForEndpoint(endpoint) {
if (endpoint.includes(MAINNET_ENDPOINT))
return SOLANA_MAINNET_CHAIN;
if (/\bdevnet\b/i.test(endpoint))
return SOLANA_DEVNET_CHAIN;
if (/\btestnet\b/i.test(endpoint))
return SOLANA_TESTNET_CHAIN;
if (/\blocalhost\b/i.test(endpoint) || /\b127\.0\.0\.1\b/.test(endpoint))
return SOLANA_LOCALNET_CHAIN;
return SOLANA_MAINNET_CHAIN;
}
/**
* TODO: docs
*/
export function getEndpointForChain(chain, endpoint) {
if (endpoint)
return endpoint;
if (chain === SOLANA_MAINNET_CHAIN)
return MAINNET_ENDPOINT;
if (chain === SOLANA_DEVNET_CHAIN)
return DEVNET_ENDPOINT;
if (chain === SOLANA_TESTNET_CHAIN)
return TESTNET_ENDPOINT;
if (chain === SOLANA_LOCALNET_CHAIN)
return LOCALNET_ENDPOINT;
return MAINNET_ENDPOINT;
}
//# sourceMappingURL=endpoint.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"endpoint.js","sourceRoot":"","sources":["../../src/endpoint.ts"],"names":[],"mappings":"AACA,OAAO,EACH,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,GACvB,MAAM,gCAAgC,CAAC;AAExC,iBAAiB;AACjB,MAAM,CAAC,MAAM,gBAAgB,GAAG,qCAAqC,CAAC;AACtE,iBAAiB;AACjB,MAAM,CAAC,MAAM,eAAe,GAAG,+BAA+B,CAAC;AAC/D,iBAAiB;AACjB,MAAM,CAAC,MAAM,gBAAgB,GAAG,gCAAgC,CAAC;AACjE,iBAAiB;AACjB,MAAM,CAAC,MAAM,iBAAiB,GAAG,uBAAuB,CAAC;AAEzD;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAChD,IAAI,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAAE,OAAO,oBAAoB,CAAC;IACrE,IAAI,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,mBAAmB,CAAC;IAC7D,IAAI,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,oBAAoB,CAAC;IAC/D,IAAI,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,qBAAqB,CAAC;IACvG,OAAO,oBAAoB,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAkB,EAAE,QAAiB;IACrE,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,IAAI,KAAK,KAAK,oBAAoB;QAAE,OAAO,gBAAgB,CAAC;IAC5D,IAAI,KAAK,KAAK,mBAAmB;QAAE,OAAO,eAAe,CAAC;IAC1D,IAAI,KAAK,KAAK,oBAAoB;QAAE,OAAO,gBAAgB,CAAC;IAC5D,IAAI,KAAK,KAAK,qBAAqB;QAAE,OAAO,iBAAiB,CAAC;IAC9D,OAAO,gBAAgB,CAAC;AAC5B,CAAC"}

View File

@@ -0,0 +1,5 @@
export * from './commitment.js';
export * from './endpoint.js';
export * from './signIn.js';
export * from './signMessage.js';
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC"}

View File

@@ -0,0 +1,176 @@
import { verifyMessageSignature } from './signMessage.js';
import { arraysEqual } from './util.js';
/**
* TODO: docs
*/
export function verifySignIn(input, output) {
const { signedMessage, signature, account: { publicKey }, } = output;
const message = deriveSignInMessage(input, output);
return (!!message && verifyMessageSignature({ message, signedMessage, signature, publicKey: publicKey }));
}
/**
* TODO: docs
*/
export function deriveSignInMessage(input, output) {
const text = deriveSignInMessageText(input, output);
if (!text)
return null;
return new TextEncoder().encode(text);
}
/**
* TODO: docs
*/
export function deriveSignInMessageText(input, output) {
const parsed = parseSignInMessage(output.signedMessage);
if (!parsed)
return null;
if (input.domain && input.domain !== parsed.domain)
return null;
if (input.address && input.address !== parsed.address)
return null;
if (input.statement !== parsed.statement)
return null;
if (input.uri !== parsed.uri)
return null;
if (input.version !== parsed.version)
return null;
if (input.chainId !== parsed.chainId)
return null;
if (input.nonce !== parsed.nonce)
return null;
if (input.issuedAt !== parsed.issuedAt)
return null;
if (input.expirationTime !== parsed.expirationTime)
return null;
if (input.notBefore !== parsed.notBefore)
return null;
if (input.requestId !== parsed.requestId)
return null;
if (input.resources) {
if (!parsed.resources)
return null;
if (!arraysEqual(input.resources, parsed.resources))
return null;
}
else if (parsed.resources)
return null;
return createSignInMessageText(parsed);
}
/**
* TODO: docs
*/
export function parseSignInMessage(message) {
const text = new TextDecoder().decode(message);
return parseSignInMessageText(text);
}
// TODO: implement https://github.com/solana-labs/solana/blob/master/docs/src/proposals/off-chain-message-signing.md
const DOMAIN = '(?<domain>[^\\n]+?) wants you to sign in with your Solana account:\\n';
const ADDRESS = '(?<address>[^\\n]+)(?:\\n|$)';
const STATEMENT = '(?:\\n(?<statement>[\\S\\s]*?)(?:\\n|$))??';
const URI = '(?:\\nURI: (?<uri>[^\\n]+))?';
const VERSION = '(?:\\nVersion: (?<version>[^\\n]+))?';
const CHAIN_ID = '(?:\\nChain ID: (?<chainId>[^\\n]+))?';
const NONCE = '(?:\\nNonce: (?<nonce>[^\\n]+))?';
const ISSUED_AT = '(?:\\nIssued At: (?<issuedAt>[^\\n]+))?';
const EXPIRATION_TIME = '(?:\\nExpiration Time: (?<expirationTime>[^\\n]+))?';
const NOT_BEFORE = '(?:\\nNot Before: (?<notBefore>[^\\n]+))?';
const REQUEST_ID = '(?:\\nRequest ID: (?<requestId>[^\\n]+))?';
const RESOURCES = '(?:\\nResources:(?<resources>(?:\\n- [^\\n]+)*))?';
const FIELDS = `${URI}${VERSION}${CHAIN_ID}${NONCE}${ISSUED_AT}${EXPIRATION_TIME}${NOT_BEFORE}${REQUEST_ID}${RESOURCES}`;
const MESSAGE = new RegExp(`^${DOMAIN}${ADDRESS}${STATEMENT}${FIELDS}\\n*$`);
/**
* TODO: docs
*/
export function parseSignInMessageText(text) {
const match = MESSAGE.exec(text);
if (!match)
return null;
const groups = match.groups;
if (!groups)
return null;
return {
domain: groups.domain,
address: groups.address,
statement: groups.statement,
uri: groups.uri,
version: groups.version,
nonce: groups.nonce,
chainId: groups.chainId,
issuedAt: groups.issuedAt,
expirationTime: groups.expirationTime,
notBefore: groups.notBefore,
requestId: groups.requestId,
resources: groups.resources?.split('\n- ').slice(1),
};
}
/**
* TODO: docs
*/
export function createSignInMessage(input) {
const text = createSignInMessageText(input);
return new TextEncoder().encode(text);
}
/**
* TODO: docs
*/
export function createSignInMessageText(input) {
// ${domain} wants you to sign in with your Solana account:
// ${address}
//
// ${statement}
//
// URI: ${uri}
// Version: ${version}
// Chain ID: ${chain}
// Nonce: ${nonce}
// Issued At: ${issued-at}
// Expiration Time: ${expiration-time}
// Not Before: ${not-before}
// Request ID: ${request-id}
// Resources:
// - ${resources[0]}
// - ${resources[1]}
// ...
// - ${resources[n]}
let message = `${input.domain} wants you to sign in with your Solana account:\n`;
message += `${input.address}`;
if (input.statement) {
message += `\n\n${input.statement}`;
}
const fields = [];
if (input.uri) {
fields.push(`URI: ${input.uri}`);
}
if (input.version) {
fields.push(`Version: ${input.version}`);
}
if (input.chainId) {
fields.push(`Chain ID: ${input.chainId}`);
}
if (input.nonce) {
fields.push(`Nonce: ${input.nonce}`);
}
if (input.issuedAt) {
fields.push(`Issued At: ${input.issuedAt}`);
}
if (input.expirationTime) {
fields.push(`Expiration Time: ${input.expirationTime}`);
}
if (input.notBefore) {
fields.push(`Not Before: ${input.notBefore}`);
}
if (input.requestId) {
fields.push(`Request ID: ${input.requestId}`);
}
if (input.resources) {
fields.push(`Resources:`);
for (const resource of input.resources) {
fields.push(`- ${resource}`);
}
}
if (fields.length) {
message += `\n\n${fields.join('\n')}`;
}
return message;
}
//# sourceMappingURL=signIn.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,18 @@
import { ed25519 } from '@noble/curves/ed25519';
import { bytesEqual } from './util.js';
/**
* TODO: docs
*/
export function verifyMessageSignature({ message, signedMessage, signature, publicKey, }) {
// TODO: implement https://github.com/solana-labs/solana/blob/master/docs/src/proposals/off-chain-message-signing.md
return bytesEqual(message, signedMessage) && ed25519.verify(signature, signedMessage, publicKey);
}
/**
* TODO: docs
*/
export function verifySignMessage(input, output) {
const { message, account: { publicKey }, } = input;
const { signedMessage, signature } = output;
return verifyMessageSignature({ message, signedMessage, signature, publicKey: publicKey });
}
//# sourceMappingURL=signMessage.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"signMessage.js","sourceRoot":"","sources":["../../src/signMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,EACnC,OAAO,EACP,aAAa,EACb,SAAS,EACT,SAAS,GAMZ;IACG,oHAAoH;IACpH,OAAO,UAAU,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;AACrG,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAA6B,EAAE,MAA+B;IAC5F,MAAM,EACF,OAAO,EACP,OAAO,EAAE,EAAE,SAAS,EAAE,GACzB,GAAG,KAAK,CAAC;IACV,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAC5C,OAAO,sBAAsB,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,SAAuB,EAAE,CAAC,CAAC;AAC7G,CAAC"}

View File

@@ -0,0 +1 @@
{"root":["../../src/commitment.ts","../../src/endpoint.ts","../../src/index.ts","../../src/signIn.ts","../../src/signMessage.ts","../../src/util.ts"],"version":"5.7.3"}

View File

@@ -0,0 +1,40 @@
/**
* @internal
*
* Efficiently compare {@link Indexed} arrays (e.g. `Array` and `Uint8Array`).
*
* @param a An array.
* @param b Another array.
*
* @return `true` if the arrays have the same length and elements, `false` otherwise.
*
* @group Internal
*/
export function arraysEqual(a, b) {
if (a === b)
return true;
const length = a.length;
if (length !== b.length)
return false;
for (let i = 0; i < length; i++) {
if (a[i] !== b[i])
return false;
}
return true;
}
/**
* @internal
*
* Efficiently compare byte arrays, using {@link arraysEqual}.
*
* @param a A byte array.
* @param b Another byte array.
*
* @return `true` if the byte arrays have the same length and bytes, `false` otherwise.
*
* @group Internal
*/
export function bytesEqual(a, b) {
return arraysEqual(a, b);
}
//# sourceMappingURL=util.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/util.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,WAAW,CAAI,CAAa,EAAE,CAAa;IACvD,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzB,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IACxB,IAAI,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAEtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9B,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;IACpC,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,UAAU,CAAC,CAAa,EAAE,CAAa;IACnD,OAAO,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC7B,CAAC"}

View File

@@ -0,0 +1,8 @@
import type { SolanaTransactionCommitment } from '@solana/wallet-standard-features';
type Commitment = 'processed' | 'confirmed' | 'finalized' | 'recent' | 'single' | 'singleGossip' | 'root' | 'max';
/**
* TODO: docs
*/
export declare function getCommitment(commitment?: Commitment): SolanaTransactionCommitment | undefined;
export {};
//# sourceMappingURL=commitment.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"commitment.d.ts","sourceRoot":"","sources":["../../src/commitment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAGpF,KAAK,UAAU,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,cAAc,GAAG,MAAM,GAAG,KAAK,CAAC;AAElH;;GAEG;AACH,wBAAgB,aAAa,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,2BAA2B,GAAG,SAAS,CAkB9F"}

View File

@@ -0,0 +1,18 @@
import type { SolanaChain } from '@solana/wallet-standard-chains';
/** TODO: docs */
export declare const MAINNET_ENDPOINT = "https://api.mainnet-beta.solana.com";
/** TODO: docs */
export declare const DEVNET_ENDPOINT = "https://api.devnet.solana.com";
/** TODO: docs */
export declare const TESTNET_ENDPOINT = "https://api.testnet.solana.com";
/** TODO: docs */
export declare const LOCALNET_ENDPOINT = "http://localhost:8899";
/**
* TODO: docs
*/
export declare function getChainForEndpoint(endpoint: string): SolanaChain;
/**
* TODO: docs
*/
export declare function getEndpointForChain(chain: SolanaChain, endpoint?: string): string;
//# sourceMappingURL=endpoint.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"endpoint.d.ts","sourceRoot":"","sources":["../../src/endpoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAQlE,iBAAiB;AACjB,eAAO,MAAM,gBAAgB,wCAAwC,CAAC;AACtE,iBAAiB;AACjB,eAAO,MAAM,eAAe,kCAAkC,CAAC;AAC/D,iBAAiB;AACjB,eAAO,MAAM,gBAAgB,mCAAmC,CAAC;AACjE,iBAAiB;AACjB,eAAO,MAAM,iBAAiB,0BAA0B,CAAC;AAEzD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAMjE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAOjF"}

View File

@@ -0,0 +1,5 @@
export * from './commitment.js';
export * from './endpoint.js';
export * from './signIn.js';
export * from './signMessage.js';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC"}

View File

@@ -0,0 +1,34 @@
import type { SolanaSignInInput, SolanaSignInOutput } from '@solana/wallet-standard-features';
/**
* TODO: docs
*/
export declare function verifySignIn(input: SolanaSignInInput, output: SolanaSignInOutput): boolean;
/**
* TODO: docs
*/
export declare function deriveSignInMessage(input: SolanaSignInInput, output: SolanaSignInOutput): Uint8Array | null;
/**
* TODO: docs
*/
export declare function deriveSignInMessageText(input: SolanaSignInInput, output: SolanaSignInOutput): string | null;
/**
* TODO: docs
*/
export type SolanaSignInInputWithRequiredFields = SolanaSignInInput & Required<Pick<SolanaSignInInput, 'domain' | 'address'>>;
/**
* TODO: docs
*/
export declare function parseSignInMessage(message: Uint8Array): SolanaSignInInputWithRequiredFields | null;
/**
* TODO: docs
*/
export declare function parseSignInMessageText(text: string): SolanaSignInInputWithRequiredFields | null;
/**
* TODO: docs
*/
export declare function createSignInMessage(input: SolanaSignInInputWithRequiredFields): Uint8Array;
/**
* TODO: docs
*/
export declare function createSignInMessageText(input: SolanaSignInInputWithRequiredFields): string;
//# sourceMappingURL=signIn.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"signIn.d.ts","sourceRoot":"","sources":["../../src/signIn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAI9F;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAU1F;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,kBAAkB,GAAG,UAAU,GAAG,IAAI,CAI3G;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,kBAAkB,GAAG,MAAM,GAAG,IAAI,CAqB3G;AAED;;GAEG;AACH,MAAM,MAAM,mCAAmC,GAAG,iBAAiB,GAC/D,QAAQ,CAAC,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC;AAE5D;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,UAAU,GAAG,mCAAmC,GAAG,IAAI,CAGlG;AAkBD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,mCAAmC,GAAG,IAAI,CAqB/F;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,mCAAmC,GAAG,UAAU,CAG1F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,mCAAmC,GAAG,MAAM,CA+D1F"}

View File

@@ -0,0 +1,15 @@
import type { SolanaSignMessageInput, SolanaSignMessageOutput } from '@solana/wallet-standard-features';
/**
* TODO: docs
*/
export declare function verifyMessageSignature({ message, signedMessage, signature, publicKey, }: {
message: Uint8Array;
signedMessage: Uint8Array;
signature: Uint8Array;
publicKey: Uint8Array;
}): boolean;
/**
* TODO: docs
*/
export declare function verifySignMessage(input: SolanaSignMessageInput, output: SolanaSignMessageOutput): boolean;
//# sourceMappingURL=signMessage.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"signMessage.d.ts","sourceRoot":"","sources":["../../src/signMessage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAGxG;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EACnC,OAAO,EACP,aAAa,EACb,SAAS,EACT,SAAS,GACZ,EAAE;IACC,OAAO,EAAE,UAAU,CAAC;IACpB,aAAa,EAAE,UAAU,CAAC;IAC1B,SAAS,EAAE,UAAU,CAAC;IACtB,SAAS,EAAE,UAAU,CAAC;CACzB,GAAG,OAAO,CAGV;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAOzG"}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=util.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/util.ts"],"names":[],"mappings":""}