@solana/addresses
Advanced tools
Comparing version 2.0.0-experimental.585314d to 2.0.0-experimental.589c379
@@ -1,7 +0,35 @@ | ||
import { base58, string } from '@metaplex-foundation/umi-serializers'; | ||
import { mapEncoder, combineCodec } from '@solana/codecs-core'; | ||
import { getStringEncoder, getStringDecoder, getBase58Encoder, getBase58Decoder } from '@solana/codecs-strings'; | ||
import { assertKeyExporterIsAvailable, assertDigestCapabilityIsAvailable } from '@solana/assertions'; | ||
// ../build-scripts/env-shim.ts | ||
var __DEV__ = /* @__PURE__ */ (() => process["env"].NODE_ENV === "development")(); | ||
function assertIsBase58EncodedAddress(putativeBase58EncodedAddress) { | ||
// src/address.ts | ||
var memoizedBase58Encoder; | ||
var memoizedBase58Decoder; | ||
function getMemoizedBase58Encoder() { | ||
if (!memoizedBase58Encoder) | ||
memoizedBase58Encoder = getBase58Encoder(); | ||
return memoizedBase58Encoder; | ||
} | ||
function getMemoizedBase58Decoder() { | ||
if (!memoizedBase58Decoder) | ||
memoizedBase58Decoder = getBase58Decoder(); | ||
return memoizedBase58Decoder; | ||
} | ||
function isAddress(putativeBase58EncodedAddress) { | ||
if ( | ||
// Lowest address (32 bytes of zeroes) | ||
putativeBase58EncodedAddress.length < 32 || // Highest address (32 bytes of 255) | ||
putativeBase58EncodedAddress.length > 44 | ||
) { | ||
return false; | ||
} | ||
const base58Encoder = getMemoizedBase58Encoder(); | ||
const bytes = base58Encoder.encode(putativeBase58EncodedAddress); | ||
const numBytes = bytes.byteLength; | ||
if (numBytes !== 32) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
function assertIsAddress(putativeBase58EncodedAddress) { | ||
try { | ||
@@ -15,3 +43,4 @@ if ( | ||
} | ||
const bytes = base58.serialize(putativeBase58EncodedAddress); | ||
const base58Encoder = getMemoizedBase58Encoder(); | ||
const bytes = base58Encoder.encode(putativeBase58EncodedAddress); | ||
const numBytes = bytes.byteLength; | ||
@@ -27,10 +56,27 @@ if (numBytes !== 32) { | ||
} | ||
function getBase58EncodedAddressCodec(config) { | ||
return string({ | ||
description: config?.description ?? (__DEV__ ? "A 32-byte account address" : ""), | ||
encoding: base58, | ||
function address(putativeBase58EncodedAddress) { | ||
assertIsAddress(putativeBase58EncodedAddress); | ||
return putativeBase58EncodedAddress; | ||
} | ||
function getAddressEncoder(config) { | ||
return mapEncoder( | ||
getStringEncoder({ | ||
description: config?.description ?? "Base58EncodedAddress", | ||
encoding: getMemoizedBase58Encoder(), | ||
size: 32 | ||
}), | ||
(putativeAddress) => address(putativeAddress) | ||
); | ||
} | ||
function getAddressDecoder(config) { | ||
return getStringDecoder({ | ||
description: config?.description ?? "Base58EncodedAddress", | ||
encoding: getMemoizedBase58Decoder(), | ||
size: 32 | ||
}); | ||
} | ||
function getBase58EncodedAddressComparator() { | ||
function getAddressCodec(config) { | ||
return combineCodec(getAddressEncoder(config), getAddressDecoder(config)); | ||
} | ||
function getAddressComparator() { | ||
return new Intl.Collator("en", { | ||
@@ -137,2 +183,17 @@ caseFirst: "lower", | ||
// src/program-derived-address.ts | ||
function isProgramDerivedAddress(value) { | ||
return Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && typeof value[1] === "number" && value[1] >= 0 && value[1] <= 255 && isAddress(value[0]); | ||
} | ||
function assertIsProgramDerivedAddress(value) { | ||
const validFormat = Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && typeof value[1] === "number"; | ||
if (!validFormat) { | ||
throw new Error( | ||
`Expected given program derived address to have the following format: [Base58EncodedAddress, ProgramDerivedAddressBump].` | ||
); | ||
} | ||
if (value[1] < 0 || value[1] > 255) { | ||
throw new Error(`Expected program derived address bump to be in the range [0, 255], got: ${value[1]}.`); | ||
} | ||
assertIsAddress(value[0]); | ||
} | ||
var MAX_SEED_LENGTH = 32; | ||
@@ -166,3 +227,6 @@ var MAX_SEEDS = 16; | ||
}; | ||
async function createProgramDerivedAddress({ programAddress, seeds }) { | ||
async function createProgramDerivedAddress({ | ||
programAddress, | ||
seeds | ||
}) { | ||
await assertDigestCapabilityIsAvailable(); | ||
@@ -181,4 +245,4 @@ if (seeds.length > MAX_SEEDS) { | ||
}, []); | ||
const base58EncodedAddressCodec = getBase58EncodedAddressCodec(); | ||
const programAddressBytes = base58EncodedAddressCodec.serialize(programAddress); | ||
const base58EncodedAddressCodec = getAddressCodec(); | ||
const programAddressBytes = base58EncodedAddressCodec.encode(programAddress); | ||
const addressBytesBuffer = await crypto.subtle.digest( | ||
@@ -192,15 +256,16 @@ "SHA-256", | ||
} | ||
return base58EncodedAddressCodec.deserialize(addressBytes)[0]; | ||
return base58EncodedAddressCodec.decode(addressBytes)[0]; | ||
} | ||
async function getProgramDerivedAddress({ programAddress, seeds }) { | ||
async function getProgramDerivedAddress({ | ||
programAddress, | ||
seeds | ||
}) { | ||
let bumpSeed = 255; | ||
while (bumpSeed > 0) { | ||
try { | ||
return { | ||
bumpSeed, | ||
pda: await createProgramDerivedAddress({ | ||
programAddress, | ||
seeds: [...seeds, new Uint8Array([bumpSeed])] | ||
}) | ||
}; | ||
const address2 = await createProgramDerivedAddress({ | ||
programAddress, | ||
seeds: [...seeds, new Uint8Array([bumpSeed])] | ||
}); | ||
return [address2, bumpSeed]; | ||
} catch (e) { | ||
@@ -216,3 +281,24 @@ if (e instanceof PointOnCurveError) { | ||
} | ||
async function getBase58EncodedAddressFromPublicKey(publicKey) { | ||
async function createAddressWithSeed({ | ||
baseAddress, | ||
programAddress, | ||
seed | ||
}) { | ||
const { encode, decode } = getAddressCodec(); | ||
const seedBytes = typeof seed === "string" ? new TextEncoder().encode(seed) : seed; | ||
if (seedBytes.byteLength > MAX_SEED_LENGTH) { | ||
throw new Error(`The seed exceeds the maximum length of 32 bytes`); | ||
} | ||
const programAddressBytes = encode(programAddress); | ||
if (programAddressBytes.length >= PDA_MARKER_BYTES.length && programAddressBytes.slice(-PDA_MARKER_BYTES.length).every((byte, index) => byte === PDA_MARKER_BYTES[index])) { | ||
throw new Error(`programAddress cannot end with the PDA marker`); | ||
} | ||
const addressBytesBuffer = await crypto.subtle.digest( | ||
"SHA-256", | ||
new Uint8Array([...encode(baseAddress), ...seedBytes, ...programAddressBytes]) | ||
); | ||
const addressBytes = new Uint8Array(addressBytesBuffer); | ||
return decode(addressBytes)[0]; | ||
} | ||
async function getAddressFromPublicKey(publicKey) { | ||
await assertKeyExporterIsAvailable(); | ||
@@ -223,8 +309,8 @@ if (publicKey.type !== "public" || publicKey.algorithm.name !== "Ed25519") { | ||
const publicKeyBytes = await crypto.subtle.exportKey("raw", publicKey); | ||
const [base58EncodedAddress] = getBase58EncodedAddressCodec().deserialize(new Uint8Array(publicKeyBytes)); | ||
const [base58EncodedAddress] = getAddressDecoder().decode(new Uint8Array(publicKeyBytes)); | ||
return base58EncodedAddress; | ||
} | ||
export { assertIsBase58EncodedAddress, getBase58EncodedAddressCodec, getBase58EncodedAddressComparator, getBase58EncodedAddressFromPublicKey, getProgramDerivedAddress }; | ||
export { address, assertIsAddress, assertIsProgramDerivedAddress, createAddressWithSeed, getAddressCodec, getAddressComparator, getAddressDecoder, getAddressEncoder, getAddressFromPublicKey, getProgramDerivedAddress, isAddress, isProgramDerivedAddress }; | ||
//# sourceMappingURL=out.js.map | ||
//# sourceMappingURL=index.browser.js.map |
@@ -5,15 +5,26 @@ this.globalThis = this.globalThis || {}; | ||
var __defProp = Object.defineProperty; | ||
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; | ||
var __publicField = (obj, key, value) => { | ||
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); | ||
return value; | ||
}; | ||
// ../../node_modules/.pnpm/@metaplex-foundation+umi-serializers-core@0.8.2/node_modules/@metaplex-foundation/umi-serializers-core/dist/esm/bytes.mjs | ||
var mergeBytes = (bytesArr) => { | ||
const totalLength = bytesArr.reduce((total, arr) => total + arr.length, 0); | ||
// ../codecs-core/dist/index.browser.js | ||
function assertByteArrayIsNotEmptyForCodec(codecDescription, bytes, offset = 0) { | ||
if (bytes.length - offset <= 0) { | ||
throw new Error(`Codec [${codecDescription}] cannot decode empty byte arrays.`); | ||
} | ||
} | ||
function assertByteArrayHasEnoughBytesForCodec(codecDescription, expected, bytes, offset = 0) { | ||
const bytesLength = bytes.length - offset; | ||
if (bytesLength < expected) { | ||
throw new Error(`Codec [${codecDescription}] expected ${expected} bytes, got ${bytesLength}.`); | ||
} | ||
} | ||
var mergeBytes = (byteArrays) => { | ||
const nonEmptyByteArrays = byteArrays.filter((arr) => arr.length); | ||
if (nonEmptyByteArrays.length === 0) { | ||
return byteArrays.length ? byteArrays[0] : new Uint8Array(); | ||
} | ||
if (nonEmptyByteArrays.length === 1) { | ||
return nonEmptyByteArrays[0]; | ||
} | ||
const totalLength = nonEmptyByteArrays.reduce((total, arr) => total + arr.length, 0); | ||
const result = new Uint8Array(totalLength); | ||
let offset = 0; | ||
bytesArr.forEach((arr) => { | ||
nonEmptyByteArrays.forEach((arr) => { | ||
result.set(arr, offset); | ||
@@ -31,34 +42,52 @@ offset += arr.length; | ||
}; | ||
var fixBytes = (bytes, length) => padBytes(bytes.slice(0, length), length); | ||
// ../../node_modules/.pnpm/@metaplex-foundation+umi-serializers-core@0.8.2/node_modules/@metaplex-foundation/umi-serializers-core/dist/esm/errors.mjs | ||
var DeserializingEmptyBufferError = class extends Error { | ||
constructor(serializer) { | ||
super(`Serializer [${serializer}] cannot deserialize empty buffers.`); | ||
__publicField(this, "name", "DeserializingEmptyBufferError"); | ||
var fixBytes = (bytes, length) => padBytes(bytes.length <= length ? bytes : bytes.slice(0, length), length); | ||
function combineCodec(encoder, decoder, description) { | ||
if (encoder.fixedSize !== decoder.fixedSize) { | ||
throw new Error( | ||
`Encoder and decoder must have the same fixed size, got [${encoder.fixedSize}] and [${decoder.fixedSize}].` | ||
); | ||
} | ||
}; | ||
var NotEnoughBytesError = class extends Error { | ||
constructor(serializer, expected, actual) { | ||
super(`Serializer [${serializer}] expected ${expected} bytes, got ${actual}.`); | ||
__publicField(this, "name", "NotEnoughBytesError"); | ||
if (encoder.maxSize !== decoder.maxSize) { | ||
throw new Error( | ||
`Encoder and decoder must have the same max size, got [${encoder.maxSize}] and [${decoder.maxSize}].` | ||
); | ||
} | ||
}; | ||
// ../../node_modules/.pnpm/@metaplex-foundation+umi-serializers-core@0.8.2/node_modules/@metaplex-foundation/umi-serializers-core/dist/esm/fixSerializer.mjs | ||
function fixSerializer(serializer, fixedBytes, description) { | ||
if (description === void 0 && encoder.description !== decoder.description) { | ||
throw new Error( | ||
`Encoder and decoder must have the same description, got [${encoder.description}] and [${decoder.description}]. Pass a custom description as a third argument if you want to override the description and bypass this error.` | ||
); | ||
} | ||
return { | ||
description: description ?? `fixed(${fixedBytes}, ${serializer.description})`, | ||
decode: decoder.decode, | ||
description: description ?? encoder.description, | ||
encode: encoder.encode, | ||
fixedSize: encoder.fixedSize, | ||
maxSize: encoder.maxSize | ||
}; | ||
} | ||
function fixCodecHelper(data, fixedBytes, description) { | ||
return { | ||
description: description ?? `fixed(${fixedBytes}, ${data.description})`, | ||
fixedSize: fixedBytes, | ||
maxSize: fixedBytes, | ||
serialize: (value) => fixBytes(serializer.serialize(value), fixedBytes), | ||
deserialize: (buffer, offset = 0) => { | ||
buffer = buffer.slice(offset, offset + fixedBytes); | ||
if (buffer.length < fixedBytes) { | ||
throw new NotEnoughBytesError("fixSerializer", fixedBytes, buffer.length); | ||
maxSize: fixedBytes | ||
}; | ||
} | ||
function fixEncoder(encoder, fixedBytes, description) { | ||
return { | ||
...fixCodecHelper(encoder, fixedBytes, description), | ||
encode: (value) => fixBytes(encoder.encode(value), fixedBytes) | ||
}; | ||
} | ||
function fixDecoder(decoder, fixedBytes, description) { | ||
return { | ||
...fixCodecHelper(decoder, fixedBytes, description), | ||
decode: (bytes, offset = 0) => { | ||
assertByteArrayHasEnoughBytesForCodec("fixCodec", fixedBytes, bytes, offset); | ||
if (offset > 0 || bytes.length > fixedBytes) { | ||
bytes = bytes.slice(offset, offset + fixedBytes); | ||
} | ||
if (serializer.fixedSize !== null) { | ||
buffer = fixBytes(buffer, serializer.fixedSize); | ||
if (decoder.fixedSize !== null) { | ||
bytes = fixBytes(bytes, decoder.fixedSize); | ||
} | ||
const [value] = serializer.deserialize(buffer, 0); | ||
const [value] = decoder.decode(bytes, 0); | ||
return [value, offset + fixedBytes]; | ||
@@ -68,29 +97,99 @@ } | ||
} | ||
function mapEncoder(encoder, unmap) { | ||
return { | ||
description: encoder.description, | ||
encode: (value) => encoder.encode(unmap(value)), | ||
fixedSize: encoder.fixedSize, | ||
maxSize: encoder.maxSize | ||
}; | ||
} | ||
// ../../node_modules/.pnpm/@metaplex-foundation+umi-serializers-encodings@0.8.2/node_modules/@metaplex-foundation/umi-serializers-encodings/dist/esm/errors.mjs | ||
var InvalidBaseStringError = class extends Error { | ||
constructor(value, base, cause) { | ||
const message = `Expected a string of base ${base}, got [${value}].`; | ||
super(message); | ||
__publicField(this, "name", "InvalidBaseStringError"); | ||
this.cause = cause; | ||
// ../codecs-numbers/dist/index.browser.js | ||
function assertNumberIsBetweenForCodec(codecDescription, min, max, value) { | ||
if (value < min || value > max) { | ||
throw new Error( | ||
`Codec [${codecDescription}] expected number to be in the range [${min}, ${max}], got ${value}.` | ||
); | ||
} | ||
}; | ||
} | ||
function sharedNumberFactory(input) { | ||
let littleEndian; | ||
let defaultDescription = input.name; | ||
if (input.size > 1) { | ||
littleEndian = !("endian" in input.options) || input.options.endian === 0; | ||
defaultDescription += littleEndian ? "(le)" : "(be)"; | ||
} | ||
return { | ||
description: input.options.description ?? defaultDescription, | ||
fixedSize: input.size, | ||
littleEndian, | ||
maxSize: input.size | ||
}; | ||
} | ||
function numberEncoderFactory(input) { | ||
const codecData = sharedNumberFactory(input); | ||
return { | ||
description: codecData.description, | ||
encode(value) { | ||
if (input.range) { | ||
assertNumberIsBetweenForCodec(input.name, input.range[0], input.range[1], value); | ||
} | ||
const arrayBuffer = new ArrayBuffer(input.size); | ||
input.set(new DataView(arrayBuffer), value, codecData.littleEndian); | ||
return new Uint8Array(arrayBuffer); | ||
}, | ||
fixedSize: codecData.fixedSize, | ||
maxSize: codecData.maxSize | ||
}; | ||
} | ||
function numberDecoderFactory(input) { | ||
const codecData = sharedNumberFactory(input); | ||
return { | ||
decode(bytes, offset = 0) { | ||
assertByteArrayIsNotEmptyForCodec(codecData.description, bytes, offset); | ||
assertByteArrayHasEnoughBytesForCodec(codecData.description, input.size, bytes, offset); | ||
const view = new DataView(toArrayBuffer(bytes, offset, input.size)); | ||
return [input.get(view, codecData.littleEndian), offset + input.size]; | ||
}, | ||
description: codecData.description, | ||
fixedSize: codecData.fixedSize, | ||
maxSize: codecData.maxSize | ||
}; | ||
} | ||
function toArrayBuffer(bytes, offset, length) { | ||
const bytesOffset = bytes.byteOffset + (offset ?? 0); | ||
const bytesLength = length ?? bytes.byteLength; | ||
return bytes.buffer.slice(bytesOffset, bytesOffset + bytesLength); | ||
} | ||
var getU32Encoder = (options = {}) => numberEncoderFactory({ | ||
name: "u32", | ||
options, | ||
range: [0, Number("0xffffffff")], | ||
set: (view, value, le) => view.setUint32(0, value, le), | ||
size: 4 | ||
}); | ||
var getU32Decoder = (options = {}) => numberDecoderFactory({ | ||
get: (view, le) => view.getUint32(0, le), | ||
name: "u32", | ||
options, | ||
size: 4 | ||
}); | ||
// ../../node_modules/.pnpm/@metaplex-foundation+umi-serializers-encodings@0.8.2/node_modules/@metaplex-foundation/umi-serializers-encodings/dist/esm/baseX.mjs | ||
var baseX = (alphabet) => { | ||
const base = alphabet.length; | ||
// ../codecs-strings/dist/index.browser.js | ||
function assertValidBaseString(alphabet4, testValue, givenValue = testValue) { | ||
if (!testValue.match(new RegExp(`^[${alphabet4}]*$`))) { | ||
throw new Error(`Expected a string of base ${alphabet4.length}, got [${givenValue}].`); | ||
} | ||
} | ||
var getBaseXEncoder = (alphabet4) => { | ||
const base = alphabet4.length; | ||
const baseBigInt = BigInt(base); | ||
return { | ||
description: `base${base}`, | ||
fixedSize: null, | ||
maxSize: null, | ||
serialize(value) { | ||
if (!value.match(new RegExp(`^[${alphabet}]*$`))) { | ||
throw new InvalidBaseStringError(value, base); | ||
} | ||
encode(value) { | ||
assertValidBaseString(alphabet4, value); | ||
if (value === "") | ||
return new Uint8Array(); | ||
const chars = [...value]; | ||
let trailIndex = chars.findIndex((c) => c !== alphabet[0]); | ||
let trailIndex = chars.findIndex((c) => c !== alphabet4[0]); | ||
trailIndex = trailIndex === -1 ? chars.length : trailIndex; | ||
@@ -104,3 +203,3 @@ const leadingZeroes = Array(trailIndex).fill(0); | ||
for (let i = tailChars.length - 1; i >= 0; i -= 1) { | ||
base10Number += baseXPower * BigInt(alphabet.indexOf(tailChars[i])); | ||
base10Number += baseXPower * BigInt(alphabet4.indexOf(tailChars[i])); | ||
baseXPower *= baseBigInt; | ||
@@ -115,26 +214,35 @@ } | ||
}, | ||
deserialize(buffer, offset = 0) { | ||
if (buffer.length === 0) | ||
fixedSize: null, | ||
maxSize: null | ||
}; | ||
}; | ||
var getBaseXDecoder = (alphabet4) => { | ||
const base = alphabet4.length; | ||
const baseBigInt = BigInt(base); | ||
return { | ||
decode(rawBytes, offset = 0) { | ||
const bytes = offset === 0 ? rawBytes : rawBytes.slice(offset); | ||
if (bytes.length === 0) | ||
return ["", 0]; | ||
const bytes = buffer.slice(offset); | ||
let trailIndex = bytes.findIndex((n) => n !== 0); | ||
trailIndex = trailIndex === -1 ? bytes.length : trailIndex; | ||
const leadingZeroes = alphabet[0].repeat(trailIndex); | ||
const leadingZeroes = alphabet4[0].repeat(trailIndex); | ||
if (trailIndex === bytes.length) | ||
return [leadingZeroes, buffer.length]; | ||
return [leadingZeroes, rawBytes.length]; | ||
let base10Number = bytes.slice(trailIndex).reduce((sum, byte) => sum * 256n + BigInt(byte), 0n); | ||
const tailChars = []; | ||
while (base10Number > 0n) { | ||
tailChars.unshift(alphabet[Number(base10Number % baseBigInt)]); | ||
tailChars.unshift(alphabet4[Number(base10Number % baseBigInt)]); | ||
base10Number /= baseBigInt; | ||
} | ||
return [leadingZeroes + tailChars.join(""), buffer.length]; | ||
} | ||
return [leadingZeroes + tailChars.join(""), rawBytes.length]; | ||
}, | ||
description: `base${base}`, | ||
fixedSize: null, | ||
maxSize: null | ||
}; | ||
}; | ||
// ../../node_modules/.pnpm/@metaplex-foundation+umi-serializers-encodings@0.8.2/node_modules/@metaplex-foundation/umi-serializers-encodings/dist/esm/base58.mjs | ||
var base58 = baseX("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"); | ||
// ../../node_modules/.pnpm/@metaplex-foundation+umi-serializers-encodings@0.8.2/node_modules/@metaplex-foundation/umi-serializers-encodings/dist/esm/nullCharacters.mjs | ||
var alphabet2 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; | ||
var getBase58Encoder = () => getBaseXEncoder(alphabet2); | ||
var getBase58Decoder = () => getBaseXDecoder(alphabet2); | ||
var removeNullCharacters = (value) => ( | ||
@@ -144,134 +252,107 @@ // eslint-disable-next-line no-control-regex | ||
); | ||
// ../../node_modules/.pnpm/@metaplex-foundation+umi-serializers-encodings@0.8.2/node_modules/@metaplex-foundation/umi-serializers-encodings/dist/esm/utf8.mjs | ||
var utf8 = { | ||
description: "utf8", | ||
fixedSize: null, | ||
maxSize: null, | ||
serialize(value) { | ||
return new TextEncoder().encode(value); | ||
}, | ||
deserialize(buffer, offset = 0) { | ||
const value = new TextDecoder().decode(buffer.slice(offset)); | ||
return [removeNullCharacters(value), buffer.length]; | ||
} | ||
var e = globalThis.TextDecoder; | ||
var o = globalThis.TextEncoder; | ||
var getUtf8Encoder = () => { | ||
let textEncoder; | ||
return { | ||
description: "utf8", | ||
encode: (value) => new Uint8Array((textEncoder || (textEncoder = new o())).encode(value)), | ||
fixedSize: null, | ||
maxSize: null | ||
}; | ||
}; | ||
// ../../node_modules/.pnpm/@metaplex-foundation+umi-serializers-numbers@0.8.2/node_modules/@metaplex-foundation/umi-serializers-numbers/dist/esm/common.mjs | ||
var Endian; | ||
(function(Endian2) { | ||
Endian2["Little"] = "le"; | ||
Endian2["Big"] = "be"; | ||
})(Endian || (Endian = {})); | ||
// ../../node_modules/.pnpm/@metaplex-foundation+umi-serializers-numbers@0.8.2/node_modules/@metaplex-foundation/umi-serializers-numbers/dist/esm/errors.mjs | ||
var NumberOutOfRangeError = class extends RangeError { | ||
constructor(serializer, min, max, actual) { | ||
super(`Serializer [${serializer}] expected number to be between ${min} and ${max}, got ${actual}.`); | ||
__publicField(this, "name", "NumberOutOfRangeError"); | ||
} | ||
}; | ||
// ../../node_modules/.pnpm/@metaplex-foundation+umi-serializers-numbers@0.8.2/node_modules/@metaplex-foundation/umi-serializers-numbers/dist/esm/utils.mjs | ||
function numberFactory(input) { | ||
let littleEndian; | ||
let defaultDescription = input.name; | ||
if (input.size > 1) { | ||
littleEndian = !("endian" in input.options) || input.options.endian === Endian.Little; | ||
defaultDescription += littleEndian ? "(le)" : "(be)"; | ||
} | ||
var getUtf8Decoder = () => { | ||
let textDecoder; | ||
return { | ||
description: input.options.description ?? defaultDescription, | ||
fixedSize: input.size, | ||
maxSize: input.size, | ||
serialize(value) { | ||
if (input.range) { | ||
assertRange(input.name, input.range[0], input.range[1], value); | ||
} | ||
const buffer = new ArrayBuffer(input.size); | ||
input.set(new DataView(buffer), value, littleEndian); | ||
return new Uint8Array(buffer); | ||
decode(bytes, offset = 0) { | ||
const value = (textDecoder || (textDecoder = new e())).decode(bytes.slice(offset)); | ||
return [removeNullCharacters(value), bytes.length]; | ||
}, | ||
deserialize(bytes, offset = 0) { | ||
const slice = bytes.slice(offset, offset + input.size); | ||
assertEnoughBytes("i8", slice, input.size); | ||
const view = toDataView(slice); | ||
return [input.get(view, littleEndian), offset + input.size]; | ||
} | ||
description: "utf8", | ||
fixedSize: null, | ||
maxSize: null | ||
}; | ||
} | ||
var toArrayBuffer = (array) => array.buffer.slice(array.byteOffset, array.byteLength + array.byteOffset); | ||
var toDataView = (array) => new DataView(toArrayBuffer(array)); | ||
var assertRange = (serializer, min, max, value) => { | ||
if (value < min || value > max) { | ||
throw new NumberOutOfRangeError(serializer, min, max, value); | ||
} | ||
}; | ||
var assertEnoughBytes = (serializer, bytes, expected) => { | ||
if (bytes.length === 0) { | ||
throw new DeserializingEmptyBufferError(serializer); | ||
var getStringEncoder = (options = {}) => { | ||
const size = options.size ?? getU32Encoder(); | ||
const encoding = options.encoding ?? getUtf8Encoder(); | ||
const description = options.description ?? `string(${encoding.description}; ${getSizeDescription(size)})`; | ||
if (size === "variable") { | ||
return { ...encoding, description }; | ||
} | ||
if (bytes.length < expected) { | ||
throw new NotEnoughBytesError(serializer, expected, bytes.length); | ||
if (typeof size === "number") { | ||
return fixEncoder(encoding, size, description); | ||
} | ||
return { | ||
description, | ||
encode: (value) => { | ||
const contentBytes = encoding.encode(value); | ||
const lengthBytes = size.encode(contentBytes.length); | ||
return mergeBytes([lengthBytes, contentBytes]); | ||
}, | ||
fixedSize: null, | ||
maxSize: null | ||
}; | ||
}; | ||
// ../../node_modules/.pnpm/@metaplex-foundation+umi-serializers-numbers@0.8.2/node_modules/@metaplex-foundation/umi-serializers-numbers/dist/esm/u32.mjs | ||
var u32 = (options = {}) => numberFactory({ | ||
name: "u32", | ||
size: 4, | ||
range: [0, Number("0xffffffff")], | ||
set: (view, value, le) => view.setUint32(0, Number(value), le), | ||
get: (view, le) => view.getUint32(0, le), | ||
options | ||
}); | ||
// ../../node_modules/.pnpm/@metaplex-foundation+umi-serializers@0.8.5/node_modules/@metaplex-foundation/umi-serializers/dist/esm/utils.mjs | ||
function getSizeDescription(size) { | ||
return typeof size === "object" ? size.description : `${size}`; | ||
} | ||
// ../../node_modules/.pnpm/@metaplex-foundation+umi-serializers@0.8.5/node_modules/@metaplex-foundation/umi-serializers/dist/esm/string.mjs | ||
function string(options = {}) { | ||
const size = options.size ?? u32(); | ||
const encoding = options.encoding ?? utf8; | ||
var getStringDecoder = (options = {}) => { | ||
const size = options.size ?? getU32Decoder(); | ||
const encoding = options.encoding ?? getUtf8Decoder(); | ||
const description = options.description ?? `string(${encoding.description}; ${getSizeDescription(size)})`; | ||
if (size === "variable") { | ||
return { | ||
...encoding, | ||
description | ||
}; | ||
return { ...encoding, description }; | ||
} | ||
if (typeof size === "number") { | ||
return fixSerializer(encoding, size, description); | ||
return fixDecoder(encoding, size, description); | ||
} | ||
return { | ||
description, | ||
fixedSize: null, | ||
maxSize: null, | ||
serialize: (value) => { | ||
const contentBytes = encoding.serialize(value); | ||
const lengthBytes = size.serialize(contentBytes.length); | ||
return mergeBytes([lengthBytes, contentBytes]); | ||
}, | ||
deserialize: (buffer, offset = 0) => { | ||
if (buffer.slice(offset).length === 0) { | ||
throw new DeserializingEmptyBufferError("string"); | ||
} | ||
const [lengthBigInt, lengthOffset] = size.deserialize(buffer, offset); | ||
decode: (bytes, offset = 0) => { | ||
assertByteArrayIsNotEmptyForCodec("string", bytes, offset); | ||
const [lengthBigInt, lengthOffset] = size.decode(bytes, offset); | ||
const length = Number(lengthBigInt); | ||
offset = lengthOffset; | ||
const contentBuffer = buffer.slice(offset, offset + length); | ||
if (contentBuffer.length < length) { | ||
throw new NotEnoughBytesError("string", length, contentBuffer.length); | ||
} | ||
const [value, contentOffset] = encoding.deserialize(contentBuffer); | ||
const contentBytes = bytes.slice(offset, offset + length); | ||
assertByteArrayHasEnoughBytesForCodec("string", length, contentBytes); | ||
const [value, contentOffset] = encoding.decode(contentBytes); | ||
offset += contentOffset; | ||
return [value, offset]; | ||
} | ||
}, | ||
description, | ||
fixedSize: null, | ||
maxSize: null | ||
}; | ||
}; | ||
function getSizeDescription(size) { | ||
return typeof size === "object" ? size.description : `${size}`; | ||
} | ||
// src/base58.ts | ||
function assertIsBase58EncodedAddress(putativeBase58EncodedAddress) { | ||
// src/address.ts | ||
var memoizedBase58Encoder; | ||
var memoizedBase58Decoder; | ||
function getMemoizedBase58Encoder() { | ||
if (!memoizedBase58Encoder) | ||
memoizedBase58Encoder = getBase58Encoder(); | ||
return memoizedBase58Encoder; | ||
} | ||
function getMemoizedBase58Decoder() { | ||
if (!memoizedBase58Decoder) | ||
memoizedBase58Decoder = getBase58Decoder(); | ||
return memoizedBase58Decoder; | ||
} | ||
function isAddress(putativeBase58EncodedAddress) { | ||
if ( | ||
// Lowest address (32 bytes of zeroes) | ||
putativeBase58EncodedAddress.length < 32 || // Highest address (32 bytes of 255) | ||
putativeBase58EncodedAddress.length > 44 | ||
) { | ||
return false; | ||
} | ||
const base58Encoder = getMemoizedBase58Encoder(); | ||
const bytes = base58Encoder.encode(putativeBase58EncodedAddress); | ||
const numBytes = bytes.byteLength; | ||
if (numBytes !== 32) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
function assertIsAddress(putativeBase58EncodedAddress) { | ||
try { | ||
@@ -285,3 +366,4 @@ if ( | ||
} | ||
const bytes = base58.serialize(putativeBase58EncodedAddress); | ||
const base58Encoder = getMemoizedBase58Encoder(); | ||
const bytes = base58Encoder.encode(putativeBase58EncodedAddress); | ||
const numBytes = bytes.byteLength; | ||
@@ -291,16 +373,33 @@ if (numBytes !== 32) { | ||
} | ||
} catch (e) { | ||
} catch (e2) { | ||
throw new Error(`\`${putativeBase58EncodedAddress}\` is not a base-58 encoded address`, { | ||
cause: e | ||
cause: e2 | ||
}); | ||
} | ||
} | ||
function getBase58EncodedAddressCodec(config) { | ||
return string({ | ||
description: config?.description ?? ("A 32-byte account address" ), | ||
encoding: base58, | ||
function address(putativeBase58EncodedAddress) { | ||
assertIsAddress(putativeBase58EncodedAddress); | ||
return putativeBase58EncodedAddress; | ||
} | ||
function getAddressEncoder(config) { | ||
return mapEncoder( | ||
getStringEncoder({ | ||
description: config?.description ?? "Base58EncodedAddress", | ||
encoding: getMemoizedBase58Encoder(), | ||
size: 32 | ||
}), | ||
(putativeAddress) => address(putativeAddress) | ||
); | ||
} | ||
function getAddressDecoder(config) { | ||
return getStringDecoder({ | ||
description: config?.description ?? "Base58EncodedAddress", | ||
encoding: getMemoizedBase58Decoder(), | ||
size: 32 | ||
}); | ||
} | ||
function getBase58EncodedAddressComparator() { | ||
function getAddressCodec(config) { | ||
return combineCodec(getAddressEncoder(config), getAddressDecoder(config)); | ||
} | ||
function getAddressComparator() { | ||
return new Intl.Collator("en", { | ||
@@ -428,2 +527,17 @@ caseFirst: "lower", | ||
// src/program-derived-address.ts | ||
function isProgramDerivedAddress(value) { | ||
return Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && typeof value[1] === "number" && value[1] >= 0 && value[1] <= 255 && isAddress(value[0]); | ||
} | ||
function assertIsProgramDerivedAddress(value) { | ||
const validFormat = Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && typeof value[1] === "number"; | ||
if (!validFormat) { | ||
throw new Error( | ||
`Expected given program derived address to have the following format: [Base58EncodedAddress, ProgramDerivedAddressBump].` | ||
); | ||
} | ||
if (value[1] < 0 || value[1] > 255) { | ||
throw new Error(`Expected program derived address bump to be in the range [0, 255], got: ${value[1]}.`); | ||
} | ||
assertIsAddress(value[0]); | ||
} | ||
var MAX_SEED_LENGTH = 32; | ||
@@ -457,3 +571,6 @@ var MAX_SEEDS = 16; | ||
}; | ||
async function createProgramDerivedAddress({ programAddress, seeds }) { | ||
async function createProgramDerivedAddress({ | ||
programAddress, | ||
seeds | ||
}) { | ||
await assertDigestCapabilityIsAvailable(); | ||
@@ -472,4 +589,4 @@ if (seeds.length > MAX_SEEDS) { | ||
}, []); | ||
const base58EncodedAddressCodec = getBase58EncodedAddressCodec(); | ||
const programAddressBytes = base58EncodedAddressCodec.serialize(programAddress); | ||
const base58EncodedAddressCodec = getAddressCodec(); | ||
const programAddressBytes = base58EncodedAddressCodec.encode(programAddress); | ||
const addressBytesBuffer = await crypto.subtle.digest( | ||
@@ -483,20 +600,21 @@ "SHA-256", | ||
} | ||
return base58EncodedAddressCodec.deserialize(addressBytes)[0]; | ||
return base58EncodedAddressCodec.decode(addressBytes)[0]; | ||
} | ||
async function getProgramDerivedAddress({ programAddress, seeds }) { | ||
async function getProgramDerivedAddress({ | ||
programAddress, | ||
seeds | ||
}) { | ||
let bumpSeed = 255; | ||
while (bumpSeed > 0) { | ||
try { | ||
return { | ||
bumpSeed, | ||
pda: await createProgramDerivedAddress({ | ||
programAddress, | ||
seeds: [...seeds, new Uint8Array([bumpSeed])] | ||
}) | ||
}; | ||
} catch (e) { | ||
if (e instanceof PointOnCurveError) { | ||
const address2 = await createProgramDerivedAddress({ | ||
programAddress, | ||
seeds: [...seeds, new Uint8Array([bumpSeed])] | ||
}); | ||
return [address2, bumpSeed]; | ||
} catch (e2) { | ||
if (e2 instanceof PointOnCurveError) { | ||
bumpSeed--; | ||
} else { | ||
throw e; | ||
throw e2; | ||
} | ||
@@ -507,5 +625,26 @@ } | ||
} | ||
async function createAddressWithSeed({ | ||
baseAddress, | ||
programAddress, | ||
seed | ||
}) { | ||
const { encode, decode } = getAddressCodec(); | ||
const seedBytes = typeof seed === "string" ? new TextEncoder().encode(seed) : seed; | ||
if (seedBytes.byteLength > MAX_SEED_LENGTH) { | ||
throw new Error(`The seed exceeds the maximum length of 32 bytes`); | ||
} | ||
const programAddressBytes = encode(programAddress); | ||
if (programAddressBytes.length >= PDA_MARKER_BYTES.length && programAddressBytes.slice(-PDA_MARKER_BYTES.length).every((byte, index) => byte === PDA_MARKER_BYTES[index])) { | ||
throw new Error(`programAddress cannot end with the PDA marker`); | ||
} | ||
const addressBytesBuffer = await crypto.subtle.digest( | ||
"SHA-256", | ||
new Uint8Array([...encode(baseAddress), ...seedBytes, ...programAddressBytes]) | ||
); | ||
const addressBytes = new Uint8Array(addressBytesBuffer); | ||
return decode(addressBytes)[0]; | ||
} | ||
// src/public-key.ts | ||
async function getBase58EncodedAddressFromPublicKey(publicKey) { | ||
async function getAddressFromPublicKey(publicKey) { | ||
await assertKeyExporterIsAvailable(); | ||
@@ -516,11 +655,18 @@ if (publicKey.type !== "public" || publicKey.algorithm.name !== "Ed25519") { | ||
const publicKeyBytes = await crypto.subtle.exportKey("raw", publicKey); | ||
const [base58EncodedAddress] = getBase58EncodedAddressCodec().deserialize(new Uint8Array(publicKeyBytes)); | ||
const [base58EncodedAddress] = getAddressDecoder().decode(new Uint8Array(publicKeyBytes)); | ||
return base58EncodedAddress; | ||
} | ||
exports.assertIsBase58EncodedAddress = assertIsBase58EncodedAddress; | ||
exports.getBase58EncodedAddressCodec = getBase58EncodedAddressCodec; | ||
exports.getBase58EncodedAddressComparator = getBase58EncodedAddressComparator; | ||
exports.getBase58EncodedAddressFromPublicKey = getBase58EncodedAddressFromPublicKey; | ||
exports.address = address; | ||
exports.assertIsAddress = assertIsAddress; | ||
exports.assertIsProgramDerivedAddress = assertIsProgramDerivedAddress; | ||
exports.createAddressWithSeed = createAddressWithSeed; | ||
exports.getAddressCodec = getAddressCodec; | ||
exports.getAddressComparator = getAddressComparator; | ||
exports.getAddressDecoder = getAddressDecoder; | ||
exports.getAddressEncoder = getAddressEncoder; | ||
exports.getAddressFromPublicKey = getAddressFromPublicKey; | ||
exports.getProgramDerivedAddress = getProgramDerivedAddress; | ||
exports.isAddress = isAddress; | ||
exports.isProgramDerivedAddress = isProgramDerivedAddress; | ||
@@ -527,0 +673,0 @@ return exports; |
@@ -1,7 +0,35 @@ | ||
import { base58, string } from '@metaplex-foundation/umi-serializers'; | ||
import { mapEncoder, combineCodec } from '@solana/codecs-core'; | ||
import { getStringEncoder, getStringDecoder, getBase58Encoder, getBase58Decoder } from '@solana/codecs-strings'; | ||
import { assertKeyExporterIsAvailable, assertDigestCapabilityIsAvailable } from '@solana/assertions'; | ||
// ../build-scripts/env-shim.ts | ||
var __DEV__ = /* @__PURE__ */ (() => process["env"].NODE_ENV === "development")(); | ||
function assertIsBase58EncodedAddress(putativeBase58EncodedAddress) { | ||
// src/address.ts | ||
var memoizedBase58Encoder; | ||
var memoizedBase58Decoder; | ||
function getMemoizedBase58Encoder() { | ||
if (!memoizedBase58Encoder) | ||
memoizedBase58Encoder = getBase58Encoder(); | ||
return memoizedBase58Encoder; | ||
} | ||
function getMemoizedBase58Decoder() { | ||
if (!memoizedBase58Decoder) | ||
memoizedBase58Decoder = getBase58Decoder(); | ||
return memoizedBase58Decoder; | ||
} | ||
function isAddress(putativeBase58EncodedAddress) { | ||
if ( | ||
// Lowest address (32 bytes of zeroes) | ||
putativeBase58EncodedAddress.length < 32 || // Highest address (32 bytes of 255) | ||
putativeBase58EncodedAddress.length > 44 | ||
) { | ||
return false; | ||
} | ||
const base58Encoder = getMemoizedBase58Encoder(); | ||
const bytes = base58Encoder.encode(putativeBase58EncodedAddress); | ||
const numBytes = bytes.byteLength; | ||
if (numBytes !== 32) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
function assertIsAddress(putativeBase58EncodedAddress) { | ||
try { | ||
@@ -15,3 +43,4 @@ if ( | ||
} | ||
const bytes = base58.serialize(putativeBase58EncodedAddress); | ||
const base58Encoder = getMemoizedBase58Encoder(); | ||
const bytes = base58Encoder.encode(putativeBase58EncodedAddress); | ||
const numBytes = bytes.byteLength; | ||
@@ -27,10 +56,27 @@ if (numBytes !== 32) { | ||
} | ||
function getBase58EncodedAddressCodec(config) { | ||
return string({ | ||
description: config?.description ?? (__DEV__ ? "A 32-byte account address" : ""), | ||
encoding: base58, | ||
function address(putativeBase58EncodedAddress) { | ||
assertIsAddress(putativeBase58EncodedAddress); | ||
return putativeBase58EncodedAddress; | ||
} | ||
function getAddressEncoder(config) { | ||
return mapEncoder( | ||
getStringEncoder({ | ||
description: config?.description ?? "Base58EncodedAddress", | ||
encoding: getMemoizedBase58Encoder(), | ||
size: 32 | ||
}), | ||
(putativeAddress) => address(putativeAddress) | ||
); | ||
} | ||
function getAddressDecoder(config) { | ||
return getStringDecoder({ | ||
description: config?.description ?? "Base58EncodedAddress", | ||
encoding: getMemoizedBase58Decoder(), | ||
size: 32 | ||
}); | ||
} | ||
function getBase58EncodedAddressComparator() { | ||
function getAddressCodec(config) { | ||
return combineCodec(getAddressEncoder(config), getAddressDecoder(config)); | ||
} | ||
function getAddressComparator() { | ||
return new Intl.Collator("en", { | ||
@@ -137,2 +183,17 @@ caseFirst: "lower", | ||
// src/program-derived-address.ts | ||
function isProgramDerivedAddress(value) { | ||
return Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && typeof value[1] === "number" && value[1] >= 0 && value[1] <= 255 && isAddress(value[0]); | ||
} | ||
function assertIsProgramDerivedAddress(value) { | ||
const validFormat = Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && typeof value[1] === "number"; | ||
if (!validFormat) { | ||
throw new Error( | ||
`Expected given program derived address to have the following format: [Base58EncodedAddress, ProgramDerivedAddressBump].` | ||
); | ||
} | ||
if (value[1] < 0 || value[1] > 255) { | ||
throw new Error(`Expected program derived address bump to be in the range [0, 255], got: ${value[1]}.`); | ||
} | ||
assertIsAddress(value[0]); | ||
} | ||
var MAX_SEED_LENGTH = 32; | ||
@@ -166,3 +227,6 @@ var MAX_SEEDS = 16; | ||
}; | ||
async function createProgramDerivedAddress({ programAddress, seeds }) { | ||
async function createProgramDerivedAddress({ | ||
programAddress, | ||
seeds | ||
}) { | ||
await assertDigestCapabilityIsAvailable(); | ||
@@ -181,4 +245,4 @@ if (seeds.length > MAX_SEEDS) { | ||
}, []); | ||
const base58EncodedAddressCodec = getBase58EncodedAddressCodec(); | ||
const programAddressBytes = base58EncodedAddressCodec.serialize(programAddress); | ||
const base58EncodedAddressCodec = getAddressCodec(); | ||
const programAddressBytes = base58EncodedAddressCodec.encode(programAddress); | ||
const addressBytesBuffer = await crypto.subtle.digest( | ||
@@ -192,15 +256,16 @@ "SHA-256", | ||
} | ||
return base58EncodedAddressCodec.deserialize(addressBytes)[0]; | ||
return base58EncodedAddressCodec.decode(addressBytes)[0]; | ||
} | ||
async function getProgramDerivedAddress({ programAddress, seeds }) { | ||
async function getProgramDerivedAddress({ | ||
programAddress, | ||
seeds | ||
}) { | ||
let bumpSeed = 255; | ||
while (bumpSeed > 0) { | ||
try { | ||
return { | ||
bumpSeed, | ||
pda: await createProgramDerivedAddress({ | ||
programAddress, | ||
seeds: [...seeds, new Uint8Array([bumpSeed])] | ||
}) | ||
}; | ||
const address2 = await createProgramDerivedAddress({ | ||
programAddress, | ||
seeds: [...seeds, new Uint8Array([bumpSeed])] | ||
}); | ||
return [address2, bumpSeed]; | ||
} catch (e) { | ||
@@ -216,3 +281,24 @@ if (e instanceof PointOnCurveError) { | ||
} | ||
async function getBase58EncodedAddressFromPublicKey(publicKey) { | ||
async function createAddressWithSeed({ | ||
baseAddress, | ||
programAddress, | ||
seed | ||
}) { | ||
const { encode, decode } = getAddressCodec(); | ||
const seedBytes = typeof seed === "string" ? new TextEncoder().encode(seed) : seed; | ||
if (seedBytes.byteLength > MAX_SEED_LENGTH) { | ||
throw new Error(`The seed exceeds the maximum length of 32 bytes`); | ||
} | ||
const programAddressBytes = encode(programAddress); | ||
if (programAddressBytes.length >= PDA_MARKER_BYTES.length && programAddressBytes.slice(-PDA_MARKER_BYTES.length).every((byte, index) => byte === PDA_MARKER_BYTES[index])) { | ||
throw new Error(`programAddress cannot end with the PDA marker`); | ||
} | ||
const addressBytesBuffer = await crypto.subtle.digest( | ||
"SHA-256", | ||
new Uint8Array([...encode(baseAddress), ...seedBytes, ...programAddressBytes]) | ||
); | ||
const addressBytes = new Uint8Array(addressBytesBuffer); | ||
return decode(addressBytes)[0]; | ||
} | ||
async function getAddressFromPublicKey(publicKey) { | ||
await assertKeyExporterIsAvailable(); | ||
@@ -223,8 +309,8 @@ if (publicKey.type !== "public" || publicKey.algorithm.name !== "Ed25519") { | ||
const publicKeyBytes = await crypto.subtle.exportKey("raw", publicKey); | ||
const [base58EncodedAddress] = getBase58EncodedAddressCodec().deserialize(new Uint8Array(publicKeyBytes)); | ||
const [base58EncodedAddress] = getAddressDecoder().decode(new Uint8Array(publicKeyBytes)); | ||
return base58EncodedAddress; | ||
} | ||
export { assertIsBase58EncodedAddress, getBase58EncodedAddressCodec, getBase58EncodedAddressComparator, getBase58EncodedAddressFromPublicKey, getProgramDerivedAddress }; | ||
export { address, assertIsAddress, assertIsProgramDerivedAddress, createAddressWithSeed, getAddressCodec, getAddressComparator, getAddressDecoder, getAddressEncoder, getAddressFromPublicKey, getProgramDerivedAddress, isAddress, isProgramDerivedAddress }; | ||
//# sourceMappingURL=out.js.map | ||
//# sourceMappingURL=index.native.js.map |
@@ -1,7 +0,35 @@ | ||
import { base58, string } from '@metaplex-foundation/umi-serializers'; | ||
import { mapEncoder, combineCodec } from '@solana/codecs-core'; | ||
import { getStringEncoder, getStringDecoder, getBase58Encoder, getBase58Decoder } from '@solana/codecs-strings'; | ||
import { assertKeyExporterIsAvailable, assertDigestCapabilityIsAvailable } from '@solana/assertions'; | ||
// ../build-scripts/env-shim.ts | ||
var __DEV__ = /* @__PURE__ */ (() => process["env"].NODE_ENV === "development")(); | ||
function assertIsBase58EncodedAddress(putativeBase58EncodedAddress) { | ||
// src/address.ts | ||
var memoizedBase58Encoder; | ||
var memoizedBase58Decoder; | ||
function getMemoizedBase58Encoder() { | ||
if (!memoizedBase58Encoder) | ||
memoizedBase58Encoder = getBase58Encoder(); | ||
return memoizedBase58Encoder; | ||
} | ||
function getMemoizedBase58Decoder() { | ||
if (!memoizedBase58Decoder) | ||
memoizedBase58Decoder = getBase58Decoder(); | ||
return memoizedBase58Decoder; | ||
} | ||
function isAddress(putativeBase58EncodedAddress) { | ||
if ( | ||
// Lowest address (32 bytes of zeroes) | ||
putativeBase58EncodedAddress.length < 32 || // Highest address (32 bytes of 255) | ||
putativeBase58EncodedAddress.length > 44 | ||
) { | ||
return false; | ||
} | ||
const base58Encoder = getMemoizedBase58Encoder(); | ||
const bytes = base58Encoder.encode(putativeBase58EncodedAddress); | ||
const numBytes = bytes.byteLength; | ||
if (numBytes !== 32) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
function assertIsAddress(putativeBase58EncodedAddress) { | ||
try { | ||
@@ -15,3 +43,4 @@ if ( | ||
} | ||
const bytes = base58.serialize(putativeBase58EncodedAddress); | ||
const base58Encoder = getMemoizedBase58Encoder(); | ||
const bytes = base58Encoder.encode(putativeBase58EncodedAddress); | ||
const numBytes = bytes.byteLength; | ||
@@ -27,10 +56,27 @@ if (numBytes !== 32) { | ||
} | ||
function getBase58EncodedAddressCodec(config) { | ||
return string({ | ||
description: config?.description ?? (__DEV__ ? "A 32-byte account address" : ""), | ||
encoding: base58, | ||
function address(putativeBase58EncodedAddress) { | ||
assertIsAddress(putativeBase58EncodedAddress); | ||
return putativeBase58EncodedAddress; | ||
} | ||
function getAddressEncoder(config) { | ||
return mapEncoder( | ||
getStringEncoder({ | ||
description: config?.description ?? "Base58EncodedAddress", | ||
encoding: getMemoizedBase58Encoder(), | ||
size: 32 | ||
}), | ||
(putativeAddress) => address(putativeAddress) | ||
); | ||
} | ||
function getAddressDecoder(config) { | ||
return getStringDecoder({ | ||
description: config?.description ?? "Base58EncodedAddress", | ||
encoding: getMemoizedBase58Decoder(), | ||
size: 32 | ||
}); | ||
} | ||
function getBase58EncodedAddressComparator() { | ||
function getAddressCodec(config) { | ||
return combineCodec(getAddressEncoder(config), getAddressDecoder(config)); | ||
} | ||
function getAddressComparator() { | ||
return new Intl.Collator("en", { | ||
@@ -137,2 +183,17 @@ caseFirst: "lower", | ||
// src/program-derived-address.ts | ||
function isProgramDerivedAddress(value) { | ||
return Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && typeof value[1] === "number" && value[1] >= 0 && value[1] <= 255 && isAddress(value[0]); | ||
} | ||
function assertIsProgramDerivedAddress(value) { | ||
const validFormat = Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && typeof value[1] === "number"; | ||
if (!validFormat) { | ||
throw new Error( | ||
`Expected given program derived address to have the following format: [Base58EncodedAddress, ProgramDerivedAddressBump].` | ||
); | ||
} | ||
if (value[1] < 0 || value[1] > 255) { | ||
throw new Error(`Expected program derived address bump to be in the range [0, 255], got: ${value[1]}.`); | ||
} | ||
assertIsAddress(value[0]); | ||
} | ||
var MAX_SEED_LENGTH = 32; | ||
@@ -166,3 +227,6 @@ var MAX_SEEDS = 16; | ||
}; | ||
async function createProgramDerivedAddress({ programAddress, seeds }) { | ||
async function createProgramDerivedAddress({ | ||
programAddress, | ||
seeds | ||
}) { | ||
await assertDigestCapabilityIsAvailable(); | ||
@@ -181,4 +245,4 @@ if (seeds.length > MAX_SEEDS) { | ||
}, []); | ||
const base58EncodedAddressCodec = getBase58EncodedAddressCodec(); | ||
const programAddressBytes = base58EncodedAddressCodec.serialize(programAddress); | ||
const base58EncodedAddressCodec = getAddressCodec(); | ||
const programAddressBytes = base58EncodedAddressCodec.encode(programAddress); | ||
const addressBytesBuffer = await crypto.subtle.digest( | ||
@@ -192,15 +256,16 @@ "SHA-256", | ||
} | ||
return base58EncodedAddressCodec.deserialize(addressBytes)[0]; | ||
return base58EncodedAddressCodec.decode(addressBytes)[0]; | ||
} | ||
async function getProgramDerivedAddress({ programAddress, seeds }) { | ||
async function getProgramDerivedAddress({ | ||
programAddress, | ||
seeds | ||
}) { | ||
let bumpSeed = 255; | ||
while (bumpSeed > 0) { | ||
try { | ||
return { | ||
bumpSeed, | ||
pda: await createProgramDerivedAddress({ | ||
programAddress, | ||
seeds: [...seeds, new Uint8Array([bumpSeed])] | ||
}) | ||
}; | ||
const address2 = await createProgramDerivedAddress({ | ||
programAddress, | ||
seeds: [...seeds, new Uint8Array([bumpSeed])] | ||
}); | ||
return [address2, bumpSeed]; | ||
} catch (e) { | ||
@@ -216,3 +281,24 @@ if (e instanceof PointOnCurveError) { | ||
} | ||
async function getBase58EncodedAddressFromPublicKey(publicKey) { | ||
async function createAddressWithSeed({ | ||
baseAddress, | ||
programAddress, | ||
seed | ||
}) { | ||
const { encode, decode } = getAddressCodec(); | ||
const seedBytes = typeof seed === "string" ? new TextEncoder().encode(seed) : seed; | ||
if (seedBytes.byteLength > MAX_SEED_LENGTH) { | ||
throw new Error(`The seed exceeds the maximum length of 32 bytes`); | ||
} | ||
const programAddressBytes = encode(programAddress); | ||
if (programAddressBytes.length >= PDA_MARKER_BYTES.length && programAddressBytes.slice(-PDA_MARKER_BYTES.length).every((byte, index) => byte === PDA_MARKER_BYTES[index])) { | ||
throw new Error(`programAddress cannot end with the PDA marker`); | ||
} | ||
const addressBytesBuffer = await crypto.subtle.digest( | ||
"SHA-256", | ||
new Uint8Array([...encode(baseAddress), ...seedBytes, ...programAddressBytes]) | ||
); | ||
const addressBytes = new Uint8Array(addressBytesBuffer); | ||
return decode(addressBytes)[0]; | ||
} | ||
async function getAddressFromPublicKey(publicKey) { | ||
await assertKeyExporterIsAvailable(); | ||
@@ -223,8 +309,8 @@ if (publicKey.type !== "public" || publicKey.algorithm.name !== "Ed25519") { | ||
const publicKeyBytes = await crypto.subtle.exportKey("raw", publicKey); | ||
const [base58EncodedAddress] = getBase58EncodedAddressCodec().deserialize(new Uint8Array(publicKeyBytes)); | ||
const [base58EncodedAddress] = getAddressDecoder().decode(new Uint8Array(publicKeyBytes)); | ||
return base58EncodedAddress; | ||
} | ||
export { assertIsBase58EncodedAddress, getBase58EncodedAddressCodec, getBase58EncodedAddressComparator, getBase58EncodedAddressFromPublicKey, getProgramDerivedAddress }; | ||
export { address, assertIsAddress, assertIsProgramDerivedAddress, createAddressWithSeed, getAddressCodec, getAddressComparator, getAddressDecoder, getAddressEncoder, getAddressFromPublicKey, getProgramDerivedAddress, isAddress, isProgramDerivedAddress }; | ||
//# sourceMappingURL=out.js.map | ||
//# sourceMappingURL=index.node.js.map |
@@ -5,9 +5,16 @@ this.globalThis = this.globalThis || {}; | ||
var X=Object.defineProperty;var M=(e,r,t)=>r in e?X(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var x=(e,r,t)=>(M(e,typeof r!="symbol"?r+"":r,t),t);var v=e=>{let r=e.reduce((i,o)=>i+o.length,0),t=new Uint8Array(r),n=0;return e.forEach(i=>{t.set(i,n),n+=i.length;}),t},_=(e,r)=>{if(e.length>=r)return e;let t=new Uint8Array(r).fill(0);return t.set(e),t},h=(e,r)=>_(e.slice(0,r),r);var b=class extends Error{constructor(t){super(`Serializer [${t}] cannot deserialize empty buffers.`);x(this,"name","DeserializingEmptyBufferError");}},y=class extends Error{constructor(t,n,i){super(`Serializer [${t}] expected ${n} bytes, got ${i}.`);x(this,"name","NotEnoughBytesError");}};function I(e,r,t){return {description:t??`fixed(${r}, ${e.description})`,fixedSize:r,maxSize:r,serialize:n=>h(e.serialize(n),r),deserialize:(n,i=0)=>{if(n=n.slice(i,i+r),n.length<r)throw new y("fixSerializer",r,n.length);e.fixedSize!==null&&(n=h(n,e.fixedSize));let[o]=e.deserialize(n,0);return [o,i+r]}}}var E=class extends Error{constructor(t,n,i){let o=`Expected a string of base ${n}, got [${t}].`;super(o);x(this,"name","InvalidBaseStringError");this.cause=i;}};var $=e=>{let r=e.length,t=BigInt(r);return {description:`base${r}`,fixedSize:null,maxSize:null,serialize(n){if(!n.match(new RegExp(`^[${e}]*$`)))throw new E(n,r);if(n==="")return new Uint8Array;let i=[...n],o=i.findIndex(d=>d!==e[0]);o=o===-1?i.length:o;let s=Array(o).fill(0);if(o===i.length)return Uint8Array.from(s);let f=i.slice(o),c=0n,l=1n;for(let d=f.length-1;d>=0;d-=1)c+=l*BigInt(e.indexOf(f[d])),l*=t;let u=[];for(;c>0n;)u.unshift(Number(c%256n)),c/=256n;return Uint8Array.from(s.concat(u))},deserialize(n,i=0){if(n.length===0)return ["",0];let o=n.slice(i),s=o.findIndex(u=>u!==0);s=s===-1?o.length:s;let f=e[0].repeat(s);if(s===o.length)return [f,n.length];let c=o.slice(s).reduce((u,d)=>u*256n+BigInt(d),0n),l=[];for(;c>0n;)l.unshift(e[Number(c%t)]),c/=t;return [f+l.join(""),n.length]}}};var w=$("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");var T=e=>e.replace(/\u0000/g,"");var C={description:"utf8",fixedSize:null,maxSize:null,serialize(e){return new TextEncoder().encode(e)},deserialize(e,r=0){let t=new TextDecoder().decode(e.slice(r));return [T(t),e.length]}};var z;(function(e){e.Little="le",e.Big="be";})(z||(z={}));var S=class extends RangeError{constructor(t,n,i,o){super(`Serializer [${t}] expected number to be between ${n} and ${i}, got ${o}.`);x(this,"name","NumberOutOfRangeError");}};function U(e){let r,t=e.name;return e.size>1&&(r=!("endian"in e.options)||e.options.endian===z.Little,t+=r?"(le)":"(be)"),{description:e.options.description??t,fixedSize:e.size,maxSize:e.size,serialize(n){e.range&&H(e.name,e.range[0],e.range[1],n);let i=new ArrayBuffer(e.size);return e.set(new DataView(i),n,r),new Uint8Array(i)},deserialize(n,i=0){let o=n.slice(i,i+e.size);W("i8",o,e.size);let s=G(o);return [e.get(s,r),i+e.size]}}}var j=e=>e.buffer.slice(e.byteOffset,e.byteLength+e.byteOffset),G=e=>new DataView(j(e)),H=(e,r,t,n)=>{if(n<r||n>t)throw new S(e,r,t,n)},W=(e,r,t)=>{if(r.length===0)throw new b(e);if(r.length<t)throw new y(e,t,r.length)};var D=(e={})=>U({name:"u32",size:4,range:[0,+"0xffffffff"],set:(r,t,n)=>r.setUint32(0,Number(t),n),get:(r,t)=>r.getUint32(0,t),options:e});function R(e){return typeof e=="object"?e.description:`${e}`}function N(e={}){let r=e.size??D(),t=e.encoding??C,n=e.description??`string(${t.description}; ${R(r)})`;return r==="variable"?{...t,description:n}:typeof r=="number"?I(t,r,n):{description:n,fixedSize:null,maxSize:null,serialize:i=>{let o=t.serialize(i),s=r.serialize(o.length);return v([s,o])},deserialize:(i,o=0)=>{if(i.slice(o).length===0)throw new b("string");let[s,f]=r.deserialize(i,o),c=Number(s);o=f;let l=i.slice(o,o+c);if(l.length<c)throw new y("string",c,l.length);let[u,d]=t.deserialize(l);return o+=d,[u,o]}}}function xr(e){try{if(e.length<32||e.length>44)throw new Error("Expected input string to decode to a byte array of length 32.");let t=w.serialize(e).byteLength;if(t!==32)throw new Error(`Expected input string to decode to a byte array of length 32. Actual length: ${t}`)}catch(r){throw new Error(`\`${e}\` is not a base-58 encoded address`,{cause:r})}}function A(e){return N({description:e?.description??"",encoding:w,size:32})}function br(){return new Intl.Collator("en",{caseFirst:"lower",ignorePunctuation:!1,localeMatcher:"best fit",numeric:!1,sensitivity:"variant",usage:"sort"}).compare}function P(){if(!globalThis.isSecureContext)throw new Error("Cryptographic operations are only allowed in secure browser contexts. Read more here: https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts")}async function O(){if(P(),typeof globalThis.crypto>"u"||typeof globalThis.crypto.subtle?.digest!="function")throw new Error("No digest implementation could be found")}async function L(){if(P(),typeof globalThis.crypto>"u"||typeof globalThis.crypto.subtle?.exportKey!="function")throw new Error("No key export implementation could be found")}var Z=37095705934669439343138083508754565189542113879843219016388785533085940283555n,p=57896044618658097711785492504343953926634992332820282019728792003956564819949n,K=19681161376707505956807079304988542015446066515923890162744021073123829784752n;function m(e){let r=e%p;return r>=0n?r:p+r}function g(e,r){let t=e;for(;r-- >0n;)t*=t,t%=p;return t}function q(e){let t=e*e%p*e%p,n=g(t,2n)*t%p,i=g(n,1n)*e%p,o=g(i,5n)*i%p,s=g(o,10n)*o%p,f=g(s,20n)*s%p,c=g(f,40n)*f%p,l=g(c,80n)*c%p,u=g(l,80n)*c%p,d=g(u,10n)*o%p;return g(d,2n)*e%p}function Y(e,r){let t=m(r*r*r),n=m(t*t*r),i=q(e*n),o=m(e*t*i),s=m(r*o*o),f=o,c=m(o*K),l=s===e,u=s===m(-e),d=s===m(-e*K);return l&&(o=f),(u||d)&&(o=c),(m(o)&1n)===1n&&(o=m(-o)),!l&&!u?null:o}function k(e,r){let t=m(e*e),n=m(t-1n),i=m(Z*t+1n),o=Y(n,i);if(o===null)return !1;let s=(r&128)!==0;return !(o===0n&&s)}function J(e){let r=e.toString(16);return r.length===1?`0${r}`:r}function Q(e){let t=`0x${e.reduce((n,i,o)=>`${J(o===31?i&-129:i)}${n}`,"")}`;return BigInt(t)}async function V(e){if(e.byteLength!==32)return !1;let r=Q(e);return k(r,e[31])}var ee=32,F=16,re=[80,114,111,103,114,97,109,68,101,114,105,118,101,100,65,100,100,114,101,115,115],B=class extends Error{};async function te({programAddress:e,seeds:r}){if(await O(),r.length>F)throw new Error(`A maximum of ${F} seeds may be supplied when creating an address`);let t,n=r.reduce((c,l,u)=>{let d=typeof l=="string"?(t||(t=new TextEncoder)).encode(l):l;if(d.byteLength>ee)throw new Error(`The seed at index ${u} exceeds the maximum length of 32 bytes`);return c.push(...d),c},[]),i=A(),o=i.serialize(e),s=await crypto.subtle.digest("SHA-256",new Uint8Array([...n,...o,...re])),f=new Uint8Array(s);if(await V(f))throw new B("Invalid seeds; point must fall off the Ed25519 curve");return i.deserialize(f)[0]}async function $r({programAddress:e,seeds:r}){let t=255;for(;t>0;)try{return {bumpSeed:t,pda:await te({programAddress:e,seeds:[...r,new Uint8Array([t])]})}}catch(n){if(n instanceof B)t--;else throw n}throw new Error("Unable to find a viable program address bump seed")}async function Lr(e){if(await L(),e.type!=="public"||e.algorithm.name!=="Ed25519")throw new Error("The `CryptoKey` must be an `Ed25519` public key");let r=await crypto.subtle.exportKey("raw",e),[t]=A().deserialize(new Uint8Array(r));return t} | ||
function y(e,r,t=0){if(r.length-t<=0)throw new Error(`Codec [${e}] cannot decode empty byte arrays.`)}function h(e,r,t,n=0){let s=t.length-n;if(s<r)throw new Error(`Codec [${e}] expected ${r} bytes, got ${s}.`)}var I=e=>{let r=e.filter(o=>o.length);if(r.length===0)return e.length?e[0]:new Uint8Array;if(r.length===1)return r[0];let t=r.reduce((o,i)=>o+i.length,0),n=new Uint8Array(t),s=0;return r.forEach(o=>{n.set(o,s),s+=o.length;}),n},Y=(e,r)=>{if(e.length>=r)return e;let t=new Uint8Array(r).fill(0);return t.set(e),t},C=(e,r)=>Y(e.length<=r?e:e.slice(0,r),r);function x(e,r,t){if(e.fixedSize!==r.fixedSize)throw new Error(`Encoder and decoder must have the same fixed size, got [${e.fixedSize}] and [${r.fixedSize}].`);if(e.maxSize!==r.maxSize)throw new Error(`Encoder and decoder must have the same max size, got [${e.maxSize}] and [${r.maxSize}].`);if(t===void 0&&e.description!==r.description)throw new Error(`Encoder and decoder must have the same description, got [${e.description}] and [${r.description}]. Pass a custom description as a third argument if you want to override the description and bypass this error.`);return {decode:r.decode,description:t??e.description,encode:e.encode,fixedSize:e.fixedSize,maxSize:e.maxSize}}function D(e,r,t){return {description:t??`fixed(${r}, ${e.description})`,fixedSize:r,maxSize:r}}function U(e,r,t){return {...D(e,r,t),encode:n=>C(e.encode(n),r)}}function T(e,r,t){return {...D(e,r,t),decode:(n,s=0)=>{h("fixCodec",r,n,s),(s>0||n.length>r)&&(n=n.slice(s,s+r)),e.fixedSize!==null&&(n=C(n,e.fixedSize));let[o]=e.decode(n,0);return [o,s+r]}}}function $(e,r){return {description:e.description,encode:t=>e.encode(r(t)),fixedSize:e.fixedSize,maxSize:e.maxSize}}function J(e,r,t,n){if(n<r||n>t)throw new Error(`Codec [${e}] expected number to be in the range [${r}, ${t}], got ${n}.`)}function P(e){let r,t=e.name;return e.size>1&&(r=!("endian"in e.options)||e.options.endian===0,t+=r?"(le)":"(be)"),{description:e.options.description??t,fixedSize:e.size,littleEndian:r,maxSize:e.size}}function Q(e){let r=P(e);return {description:r.description,encode(t){e.range&&J(e.name,e.range[0],e.range[1],t);let n=new ArrayBuffer(e.size);return e.set(new DataView(n),t,r.littleEndian),new Uint8Array(n)},fixedSize:r.fixedSize,maxSize:r.maxSize}}function ee(e){let r=P(e);return {decode(t,n=0){y(r.description,t,n),h(r.description,e.size,t,n);let s=new DataView(re(t,n,e.size));return [e.get(s,r.littleEndian),n+e.size]},description:r.description,fixedSize:r.fixedSize,maxSize:r.maxSize}}function re(e,r,t){let n=e.byteOffset+(r??0),s=t??e.byteLength;return e.buffer.slice(n,n+s)}var N=(e={})=>Q({name:"u32",options:e,range:[0,+"0xffffffff"],set:(r,t,n)=>r.setUint32(0,t,n),size:4}),F=(e={})=>ee({get:(r,t)=>r.getUint32(0,t),name:"u32",options:e,size:4});function te(e,r,t=r){if(!r.match(new RegExp(`^[${e}]*$`)))throw new Error(`Expected a string of base ${e.length}, got [${t}].`)}var ne=e=>{let r=e.length,t=BigInt(r);return {description:`base${r}`,encode(n){if(te(e,n),n==="")return new Uint8Array;let s=[...n],o=s.findIndex(g=>g!==e[0]);o=o===-1?s.length:o;let i=Array(o).fill(0);if(o===s.length)return Uint8Array.from(i);let a=s.slice(o),d=0n,c=1n;for(let g=a.length-1;g>=0;g-=1)d+=c*BigInt(e.indexOf(a[g])),c*=t;let f=[];for(;d>0n;)f.unshift(Number(d%256n)),d/=256n;return Uint8Array.from(i.concat(f))},fixedSize:null,maxSize:null}},oe=e=>{let r=e.length,t=BigInt(r);return {decode(n,s=0){let o=s===0?n:n.slice(s);if(o.length===0)return ["",0];let i=o.findIndex(f=>f!==0);i=i===-1?o.length:i;let a=e[0].repeat(i);if(i===o.length)return [a,n.length];let d=o.slice(i).reduce((f,g)=>f*256n+BigInt(g),0n),c=[];for(;d>0n;)c.unshift(e[Number(d%t)]),d/=t;return [a+c.join(""),n.length]},description:`base${r}`,fixedSize:null,maxSize:null}};var _="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",O=()=>ne(_),R=()=>oe(_);var se=e=>e.replace(/\u0000/g,"");var ie=globalThis.TextDecoder,de=globalThis.TextEncoder,ce=()=>{let e;return {description:"utf8",encode:r=>new Uint8Array((e||(e=new de)).encode(r)),fixedSize:null,maxSize:null}},ae=()=>{let e;return {decode(r,t=0){let n=(e||(e=new ie)).decode(r.slice(t));return [se(n),r.length]},description:"utf8",fixedSize:null,maxSize:null}};var L=(e={})=>{let r=e.size??N(),t=e.encoding??ce(),n=e.description??`string(${t.description}; ${K(r)})`;return r==="variable"?{...t,description:n}:typeof r=="number"?U(t,r,n):{description:n,encode:s=>{let o=t.encode(s),i=r.encode(o.length);return I([i,o])},fixedSize:null,maxSize:null}},k=(e={})=>{let r=e.size??F(),t=e.encoding??ae(),n=e.description??`string(${t.description}; ${K(r)})`;return r==="variable"?{...t,description:n}:typeof r=="number"?T(t,r,n):{decode:(s,o=0)=>{y("string",s,o);let[i,a]=r.decode(s,o),d=Number(i);o=a;let c=s.slice(o,o+d);h("string",d,c);let[f,g]=t.decode(c);return o+=g,[f,o]},description:n,fixedSize:null,maxSize:null}};function K(e){return typeof e=="object"?e.description:`${e}`}var v,A;function z(){return v||(v=O()),v}function fe(){return A||(A=R()),A}function M(e){return !(e.length<32||e.length>44||z().encode(e).byteLength!==32)}function w(e){try{if(e.length<32||e.length>44)throw new Error("Expected input string to decode to a byte array of length 32.");let n=z().encode(e).byteLength;if(n!==32)throw new Error(`Expected input string to decode to a byte array of length 32. Actual length: ${n}`)}catch(r){throw new Error(`\`${e}\` is not a base-58 encoded address`,{cause:r})}}function ge(e){return w(e),e}function ue(e){return $(L({description:e?.description??"Base58EncodedAddress",encoding:z(),size:32}),r=>ge(r))}function B(e){return k({description:e?.description??"Base58EncodedAddress",encoding:fe(),size:32})}function S(e){return x(ue(e),B(e))}function Fe(){return new Intl.Collator("en",{caseFirst:"lower",ignorePunctuation:!1,localeMatcher:"best fit",numeric:!1,sensitivity:"variant",usage:"sort"}).compare}function X(){if(!globalThis.isSecureContext)throw new Error("Cryptographic operations are only allowed in secure browser contexts. Read more here: https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts")}async function H(){if(X(),typeof globalThis.crypto>"u"||typeof globalThis.crypto.subtle?.digest!="function")throw new Error("No digest implementation could be found")}async function V(){if(X(),typeof globalThis.crypto>"u"||typeof globalThis.crypto.subtle?.exportKey!="function")throw new Error("No key export implementation could be found")}var le=37095705934669439343138083508754565189542113879843219016388785533085940283555n,u=57896044618658097711785492504343953926634992332820282019728792003956564819949n,G=19681161376707505956807079304988542015446066515923890162744021073123829784752n;function l(e){let r=e%u;return r>=0n?r:u+r}function m(e,r){let t=e;for(;r-- >0n;)t*=t,t%=u;return t}function me(e){let t=e*e%u*e%u,n=m(t,2n)*t%u,s=m(n,1n)*e%u,o=m(s,5n)*s%u,i=m(o,10n)*o%u,a=m(i,20n)*i%u,d=m(a,40n)*a%u,c=m(d,80n)*d%u,f=m(c,80n)*d%u,g=m(f,10n)*o%u;return m(g,2n)*e%u}function pe(e,r){let t=l(r*r*r),n=l(t*t*r),s=me(e*n),o=l(e*t*s),i=l(r*o*o),a=o,d=l(o*G),c=i===e,f=i===l(-e),g=i===l(-e*G);return c&&(o=a),(f||g)&&(o=d),(l(o)&1n)===1n&&(o=l(-o)),!c&&!f?null:o}function j(e,r){let t=l(e*e),n=l(t-1n),s=l(le*t+1n),o=pe(n,s);if(o===null)return !1;let i=(r&128)!==0;return !(o===0n&&i)}function he(e){let r=e.toString(16);return r.length===1?`0${r}`:r}function ye(e){let t=`0x${e.reduce((n,s,o)=>`${he(o===31?s&-129:s)}${n}`,"")}`;return BigInt(t)}async function W(e){if(e.byteLength!==32)return !1;let r=ye(e);return j(r,e[31])}function qe(e){return Array.isArray(e)&&e.length===2&&typeof e[0]=="string"&&typeof e[1]=="number"&&e[1]>=0&&e[1]<=255&&M(e[0])}function Ze(e){if(!(Array.isArray(e)&&e.length===2&&typeof e[0]=="string"&&typeof e[1]=="number"))throw new Error("Expected given program derived address to have the following format: [Base58EncodedAddress, ProgramDerivedAddressBump].");if(e[1]<0||e[1]>255)throw new Error(`Expected program derived address bump to be in the range [0, 255], got: ${e[1]}.`);w(e[0]);}var Z=32,q=16,b=[80,114,111,103,114,97,109,68,101,114,105,118,101,100,65,100,100,114,101,115,115],E=class extends Error{};async function xe({programAddress:e,seeds:r}){if(await H(),r.length>q)throw new Error(`A maximum of ${q} seeds may be supplied when creating an address`);let t,n=r.reduce((d,c,f)=>{let g=typeof c=="string"?(t||(t=new TextEncoder)).encode(c):c;if(g.byteLength>Z)throw new Error(`The seed at index ${f} exceeds the maximum length of 32 bytes`);return d.push(...g),d},[]),s=S(),o=s.encode(e),i=await crypto.subtle.digest("SHA-256",new Uint8Array([...n,...o,...b])),a=new Uint8Array(i);if(await W(a))throw new E("Invalid seeds; point must fall off the Ed25519 curve");return s.decode(a)[0]}async function Ye({programAddress:e,seeds:r}){let t=255;for(;t>0;)try{return [await xe({programAddress:e,seeds:[...r,new Uint8Array([t])]}),t]}catch(n){if(n instanceof E)t--;else throw n}throw new Error("Unable to find a viable program address bump seed")}async function Je({baseAddress:e,programAddress:r,seed:t}){let{encode:n,decode:s}=S(),o=typeof t=="string"?new TextEncoder().encode(t):t;if(o.byteLength>Z)throw new Error("The seed exceeds the maximum length of 32 bytes");let i=n(r);if(i.length>=b.length&&i.slice(-b.length).every((c,f)=>c===b[f]))throw new Error("programAddress cannot end with the PDA marker");let a=await crypto.subtle.digest("SHA-256",new Uint8Array([...n(e),...o,...i])),d=new Uint8Array(a);return s(d)[0]}async function or(e){if(await V(),e.type!=="public"||e.algorithm.name!=="Ed25519")throw new Error("The `CryptoKey` must be an `Ed25519` public key");let r=await crypto.subtle.exportKey("raw",e),[t]=B().decode(new Uint8Array(r));return t} | ||
exports.assertIsBase58EncodedAddress = xr; | ||
exports.getBase58EncodedAddressCodec = A; | ||
exports.getBase58EncodedAddressComparator = br; | ||
exports.getBase58EncodedAddressFromPublicKey = Lr; | ||
exports.getProgramDerivedAddress = $r; | ||
exports.address = ge; | ||
exports.assertIsAddress = w; | ||
exports.assertIsProgramDerivedAddress = Ze; | ||
exports.createAddressWithSeed = Je; | ||
exports.getAddressCodec = S; | ||
exports.getAddressComparator = Fe; | ||
exports.getAddressDecoder = B; | ||
exports.getAddressEncoder = ue; | ||
exports.getAddressFromPublicKey = or; | ||
exports.getProgramDerivedAddress = Ye; | ||
exports.isAddress = M; | ||
exports.isProgramDerivedAddress = qe; | ||
@@ -14,0 +21,0 @@ return exports; |
@@ -1,4 +0,4 @@ | ||
export * from './base58'; | ||
export * from './address'; | ||
export * from './program-derived-address'; | ||
export * from './public-key'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -1,12 +0,38 @@ | ||
import { Base58EncodedAddress } from './base58'; | ||
type PDAInput = Readonly<{ | ||
import { Base58EncodedAddress } from './address'; | ||
/** | ||
* An address derived from a program address and a set of seeds. | ||
* It includes the bump seed used to derive the address and | ||
* ensure the address is not on the Ed25519 curve. | ||
*/ | ||
export type ProgramDerivedAddress<TAddress extends string = string> = Readonly<[ | ||
Base58EncodedAddress<TAddress>, | ||
ProgramDerivedAddressBump | ||
]>; | ||
/** | ||
* A number between 0 and 255, inclusive. | ||
*/ | ||
export type ProgramDerivedAddressBump = number & { | ||
readonly __brand: unique symbol; | ||
}; | ||
/** | ||
* Returns true if the input value is a program derived address. | ||
*/ | ||
export declare function isProgramDerivedAddress<TAddress extends string = string>(value: unknown): value is ProgramDerivedAddress<TAddress>; | ||
/** | ||
* Fails if the input value is not a program derived address. | ||
*/ | ||
export declare function assertIsProgramDerivedAddress<TAddress extends string = string>(value: unknown): asserts value is ProgramDerivedAddress<TAddress>; | ||
type ProgramDerivedAddressInput = Readonly<{ | ||
programAddress: Base58EncodedAddress; | ||
seeds: Seed[]; | ||
}>; | ||
type SeedInput = Readonly<{ | ||
baseAddress: Base58EncodedAddress; | ||
programAddress: Base58EncodedAddress; | ||
seed: Seed; | ||
}>; | ||
type Seed = string | Uint8Array; | ||
export declare function getProgramDerivedAddress({ programAddress, seeds }: PDAInput): Promise<Readonly<{ | ||
bumpSeed: number; | ||
pda: Base58EncodedAddress; | ||
}>>; | ||
export declare function getProgramDerivedAddress({ programAddress, seeds, }: ProgramDerivedAddressInput): Promise<ProgramDerivedAddress>; | ||
export declare function createAddressWithSeed({ baseAddress, programAddress, seed, }: SeedInput): Promise<Base58EncodedAddress>; | ||
export {}; | ||
//# sourceMappingURL=program-derived-address.d.ts.map |
@@ -1,3 +0,3 @@ | ||
import { Base58EncodedAddress } from './base58'; | ||
export declare function getBase58EncodedAddressFromPublicKey(publicKey: CryptoKey): Promise<Base58EncodedAddress>; | ||
import { Base58EncodedAddress } from './address'; | ||
export declare function getAddressFromPublicKey(publicKey: CryptoKey): Promise<Base58EncodedAddress>; | ||
//# sourceMappingURL=public-key.d.ts.map |
{ | ||
"name": "@solana/addresses", | ||
"version": "2.0.0-experimental.585314d", | ||
"version": "2.0.0-experimental.589c379", | ||
"description": "Helpers for generating account addresses", | ||
@@ -52,22 +52,23 @@ "exports": { | ||
"dependencies": { | ||
"@metaplex-foundation/umi-serializers": "^0.8.5", | ||
"@solana/assertions": "2.0.0-experimental.585314d" | ||
"@solana/assertions": "2.0.0-experimental.589c379", | ||
"@solana/codecs-core": "2.0.0-experimental.589c379", | ||
"@solana/codecs-strings": "2.0.0-experimental.589c379" | ||
}, | ||
"devDependencies": { | ||
"@solana/eslint-config-solana": "^1.0.2", | ||
"@swc/jest": "^0.2.27", | ||
"@types/jest": "^29.5.3", | ||
"@typescript-eslint/eslint-plugin": "^6.0.0", | ||
"@typescript-eslint/parser": "^6.0.0", | ||
"@swc/jest": "^0.2.29", | ||
"@types/jest": "^29.5.6", | ||
"@typescript-eslint/eslint-plugin": "^6.7.0", | ||
"@typescript-eslint/parser": "^6.3.0", | ||
"agadoo": "^3.0.0", | ||
"eslint": "^8.45.0", | ||
"eslint-plugin-jest": "^27.2.3", | ||
"eslint-plugin-jest": "^27.4.2", | ||
"eslint-plugin-sort-keys-fix": "^1.1.2", | ||
"jest": "^29.6.1", | ||
"jest-environment-jsdom": "^29.6.0", | ||
"jest-runner-eslint": "^2.1.0", | ||
"jest": "^29.7.0", | ||
"jest-environment-jsdom": "^29.7.0", | ||
"jest-runner-eslint": "^2.1.2", | ||
"jest-runner-prettier": "^1.0.0", | ||
"prettier": "^2.8.8", | ||
"prettier": "^2.8", | ||
"tsup": "7.2.0", | ||
"typescript": "^5.1.6", | ||
"typescript": "^5.2.2", | ||
"version-from-git": "^1.1.1", | ||
@@ -91,7 +92,8 @@ "build-scripts": "0.0.0", | ||
"publish-packages": "pnpm publish --tag experimental --access public --no-git-checks", | ||
"style:fix": "pnpm eslint --fix src/* && pnpm prettier -w src/* package.json", | ||
"test:lint": "jest -c node_modules/test-config/jest-lint.config.ts --rootDir . --silent", | ||
"test:prettier": "jest -c node_modules/test-config/jest-prettier.config.ts --rootDir . --silent", | ||
"test:treeshakability:browser": "agadoo dist/index.browser.js", | ||
"test:treeshakability:native": "agadoo dist/index.node.js", | ||
"test:treeshakability:node": "agadoo dist/index.native.js", | ||
"test:treeshakability:native": "agadoo dist/index.native.js", | ||
"test:treeshakability:node": "agadoo dist/index.node.js", | ||
"test:typecheck": "tsc --noEmit", | ||
@@ -98,0 +100,0 @@ "test:unit:browser": "jest -c node_modules/test-config/jest-unit.config.browser.ts --rootDir . --silent", |
133
README.md
@@ -25,14 +25,43 @@ [![npm][npm-image]][npm-url] | ||
Whenever you need to validate an arbitrary string as a base58-encoded address, use the `assertIsBase58EncodedAddress()` function in this package. | ||
Whenever you need to validate an arbitrary string as a base58-encoded address, use the `address()`, `assertIsAddress()`, or `isAddress()` functions in this package. | ||
### `ProgramDerivedAddress` | ||
This type represents the tuple of a program derived address and the bump seed used to ensure that the address, as derived, is not found on the Ed25519 curve. | ||
Whenever you need to validate an arbitrary tuple as one that represents a program derived address, use the `assertIsProgramDerivedAddress()` or `isProgramDerivedAddress()` functions in this package. | ||
### `ProgramDerivedAddressBump` | ||
This type represents an integer between 0-255 used as a seed when deriving a program derived address. The purpose of this value is to modify the derivation enough to ensure that the derived address does not find itself on the Ed25519 curve. | ||
## Functions | ||
### `assertIsBase58EncodedAddress()` | ||
### `address()` | ||
This helper combines _asserting_ that a string is an address with _coercing_ it to the `Base58EncodedAddress` type. It's best used with untrusted input. | ||
```ts | ||
import { address } from '@solana/addresses'; | ||
await transfer(address(fromAddress), address(toAddress), lamports(100000n)); | ||
``` | ||
When starting from a known-good address as a string, it's more efficient to typecast it rather than to use the `address()` helper, because the helper unconditionally performs validation on its input. | ||
```ts | ||
import { Base58EncodedAddress } from '@solana/addresses'; | ||
const MEMO_PROGRAM_ADDRESS = | ||
'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr' as Base58EncodedAddress<'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'>; | ||
``` | ||
### `assertIsAddress()` | ||
Client applications primarily deal with addresses and public keys in the form of base58-encoded strings. Addresses returned from the RPC API conform to the type `Base58EncodedAddress`. You can use a value of that type wherever a base58-encoded address is expected. | ||
From time to time you might acquire a string, that you expect to validate as an address, from an untrusted network API or user input. To assert that such an arbitrary string is a base58-encoded address, use the `assertIsBase58EncodedAddress` function. | ||
From time to time you might acquire a string, that you expect to validate as an address, from an untrusted network API or user input. To assert that such an arbitrary string is a base58-encoded address, use the `assertIsAddress` function. | ||
```ts | ||
import { assertIsBase58EncodedAddress } from '@solana/addresses'; | ||
import { assertIsAddress } from '@solana/addresses'; | ||
@@ -46,3 +75,3 @@ // Imagine a function that fetches an account's balance when a user submits a form. | ||
// Typescript will upcast `address` to `Base58EncodedAddress`. | ||
assertIsBase58EncodedAddress(address); | ||
assertIsAddress(address); | ||
// At this point, `address` is a `Base58EncodedAddress` that can be used with the RPC. | ||
@@ -56,10 +85,65 @@ const balanceInLamports = await rpc.getBalance(address).send(); | ||
### `getBase58EncodedAddressFromPublicKey()` | ||
### `assertIsProgramDerivedAddress()` | ||
In the event that you receive an address/bump-seed tuple from some untrusted source, you can assert that such an tuple conforms to the `ProgramDerivedAddress` type using this function. | ||
See [`assertIsAddress()`](#assertisaddress) for an example of how to use an assertion function. | ||
### `createAddressWithSeed()` | ||
Returns a base58-encoded address derived from some base address, some program address, and a seed string or byte array. | ||
```ts | ||
import { createAddressWithSeed } from '@solana/addresses'; | ||
const derivedAddress = await createAddressWithSeed({ | ||
// The private key associated with this address will be able to sign for `derivedAddress`. | ||
baseAddress: 'B9Lf9z5BfNPT4d5KMeaBFx8x1G4CULZYR1jA2kmxRDka' as Base58EncodedAddress, | ||
// Only this program will be able to write data to this account. | ||
programAddress: '445erYq578p2aERrGW9mn9KiYe3fuG6uHdcJ2LPPShGw' as Base58EncodedAddress, | ||
seed: 'data-account', | ||
}); | ||
``` | ||
### `getAddressDecoder()` | ||
Returns a decoder that you can use to convert an array of 32 bytes representing an address to the base58-encoded representation of that address. Returns a tuple of the `Base58EncodedAddress` and the offset within the byte array at which the decoder stopped reading. | ||
```ts | ||
import { getAddressDecoder } from '@solana/addresses'; | ||
const addressBytes = new Uint8Array([ | ||
150, 183, 190, 48, 171, 8, 39, 156, 122, 213, 172, 108, 193, 95, 26, 158, 149, 243, 115, 254, 20, 200, 36, 30, 248, | ||
179, 178, 232, 220, 89, 53, 127, | ||
]); | ||
const addressDecoder = getAddressDecoder(); | ||
const [address, offset] = addressDecoder.decode(address); // [B9Lf9z5BfNPT4d5KMeaBFx8x1G4CULZYR1jA2kmxRDka, 32] | ||
``` | ||
### `getAddressEncoder()` | ||
Returns an encoder that you can use to encode a base58-encoded address to a byte array. | ||
```ts | ||
import { getAddressEncoder } from '@solana/addresses'; | ||
const address = 'B9Lf9z5BfNPT4d5KMeaBFx8x1G4CULZYR1jA2kmxRDka' as Base58EncodedAddress; | ||
const addressEncoder = getAddressEncoder(); | ||
const addressBytes = addressEncoder.encode(address); | ||
// Uint8Array(32) [ | ||
// 150, 183, 190, 48, 171, 8, 39, 156, | ||
// 122, 213, 172, 108, 193, 95, 26, 158, | ||
// 149, 243, 115, 254, 20, 200, 36, 30, | ||
// 248, 179, 178, 232, 220, 89, 53, 127 | ||
// ] | ||
``` | ||
### `getAddressFromPublicKey()` | ||
Given a public `CryptoKey`, this method will return its associated `Base58EncodedAddress`. | ||
```ts | ||
import { getBase58EncodedAddressFromPublicKey } from '@solana/addresses'; | ||
import { getAddressFromPublicKey } from '@solana/addresses'; | ||
const address = await getBase58EncodedAddressFromPublicKey(publicKey); | ||
const address = await getAddressFromPublicKey(publicKey); | ||
``` | ||
@@ -72,5 +156,5 @@ | ||
```ts | ||
import { getBase58EncodedAddressCodec, getProgramDerivedAddress } from '@solana/addresses'; | ||
import { getAddressEncoder, getProgramDerivedAddress } from '@solana/addresses'; | ||
const { serialize } = getBase58EncodedAddressCodec(); | ||
const addressEncoder = getAddressEncoder(); | ||
const { bumpSeed, pda } = await getProgramDerivedAddress({ | ||
@@ -80,9 +164,32 @@ programAddress: 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL' as Base58EncodedAddress, | ||
// Owner | ||
serialize('9fYLFVoVqwH37C3dyPi6cpeobfbQ2jtLpN5HgAYDDdkm' as Base58EncodedAddress), | ||
addressEncoder.encode('9fYLFVoVqwH37C3dyPi6cpeobfbQ2jtLpN5HgAYDDdkm' as Base58EncodedAddress), | ||
// Token program | ||
serialize('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' as Base58EncodedAddress), | ||
addressEncoder.encode('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' as Base58EncodedAddress), | ||
// Mint | ||
serialize('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' as Base58EncodedAddress), | ||
addressEncoder.encode('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' as Base58EncodedAddress), | ||
], | ||
}); | ||
``` | ||
### `isAddress()` | ||
This is a type guard that accepts a string as input. It will both return `true` if the string conforms to the `Base58EncodedAddress` type and will refine the type for use in your program. | ||
```ts | ||
import { isAddress } from '@solana/addresses'; | ||
if (isAddress(ownerAddress)) { | ||
// At this point, `ownerAddress` has been refined to a | ||
// `Base58EncodedAddress` that can be used with the RPC. | ||
const { value: lamports } = await rpc.getBalance(ownerAddress).send(); | ||
setBalanceLamports(lamports); | ||
} else { | ||
setError(`${ownerAddress} is not an address`); | ||
} | ||
``` | ||
### `isProgramDerivedAddress()` | ||
This is a type guard that accepts a tuple as input. It will both return `true` if the tuple conforms to the `ProgramDerivedAddress` type and will refine the type for use in your program. | ||
See [`isAddress()`](#isaddress) for an example of how to use a type guard. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
283438
2613
191
3
23
9
+ Added@solana/assertions@2.0.0-experimental.589c379(transitive)
+ Added@solana/codecs-core@2.0.0-experimental.589c379(transitive)
+ Added@solana/codecs-numbers@2.0.0-experimental.589c379(transitive)
+ Added@solana/codecs-strings@2.0.0-experimental.589c379(transitive)
+ Addedfastestsmallesttextencoderdecoder@1.0.22(transitive)
- Removed@metaplex-foundation/umi-options@0.8.9(transitive)
- Removed@metaplex-foundation/umi-public-keys@0.8.9(transitive)
- Removed@metaplex-foundation/umi-serializers@0.8.9(transitive)
- Removed@metaplex-foundation/umi-serializers-core@0.8.9(transitive)
- Removed@metaplex-foundation/umi-serializers-encodings@0.8.9(transitive)
- Removed@metaplex-foundation/umi-serializers-numbers@0.8.9(transitive)
- Removed@solana/assertions@2.0.0-experimental.585314d(transitive)