UNPKG

@infinixjoyd/metaplex-auth-service

Version:

A client library for nft.storage designed for metaplex NFT uploads

119 lines (118 loc) 4.7 kB
import { base58btc } from 'multiformats/bases/base58'; import * as varint from 'varint'; import nacl from 'tweetnacl'; /** * Request tag indicating what blockchain will be used to mint. Currently, the value * will always be set to `"solana"` and cannot be overridden by the user. */ export const TagChain = 'chain'; /** * Request tag indicating which [Solana cluster](https://docs.solana.com/clusters) will be * used to mint. * * Currently this library will accept any string value, however it is strongly * recommended that you use one of these "canonical" values: `"devnet"`, `"mainnet-beta"`, `"testnet"`. * This may be enforced by the backend at a later date. */ export const TagSolanaCluster = 'solanaCluster'; /** * Request tag indicating which "user agent" or tool is being used to prepare the upload. This should be * set to a string that includes the name of the tool or platform. * * Projects using this library are free to choose their own value for this tag, however you should avoid * changing the name over time, unless the project itself changes names (for example, due to a community fork or re-branding). * * For personal projects or individuals creating tools that are not affiliated with a public platform, please set the * value to a URL for your code repository. If your code is not yet public, please create a repository containing a * description of the project and links to its public-facing interface. * * Examples of suitable values: * * - `"metaplex/candy-machine-cli"` * - `"metaplex/js-sdk"` * - `"magiceden/mint-authority"` * - `"https://github.com/samuelvanderwaal/metaboss"` * */ export const TagMintingAgent = 'mintingAgent'; /** * Optional request tag indicating which version of the "minting agent" was used to prepare the request. * This may contain arbitrary text, as each project may have their own versioning scheme. */ export const TagMintingAgentVersion = 'agentVersion'; const DEFAULT_CLUSTER = 'devnet'; const MulticodecEd25519Pubkey = varint.encode(0xed); export function MetaplexAuthWithSigner(signMessage, publicKey, opts) { const chain = 'solana'; const solanaCluster = opts.solanaCluster || DEFAULT_CLUSTER; const { mintingAgent, agentVersion } = opts; if (!mintingAgent) { throw new Error('required option "mintingAgent" not provided'); } return { chain, solanaCluster, mintingAgent, agentVersion, signMessage, publicKey, }; } export function MetaplexAuthWithSecretKey(privkey, opts) { const { publicKey, secretKey } = nacl.sign.keyPair.fromSecretKey(privkey); const signMessage = async (message) => { return nacl.sign.detached(message, secretKey); }; return MetaplexAuthWithSigner(signMessage, publicKey, opts); } export async function makeMetaplexUploadToken(auth, public_key, rootCID) { const tags = { [TagChain]: auth.chain, [TagSolanaCluster]: auth.solanaCluster, [TagMintingAgent]: auth.mintingAgent, [TagMintingAgentVersion]: auth.agentVersion, }; const req = { put: { rootCID, tags, }, }; const iss = keyDID(public_key); const payload = { iss, req, }; const headerB64 = objectToB64URL({ alg: 'EdDSA', typ: 'JWT' }); const payloadB64 = objectToB64URL(payload); const encoded = headerB64 + '.' + payloadB64; const encodedBytes = new TextEncoder().encode(encoded); const sig = await auth.signMessage(encodedBytes); const sigB64 = b64urlEncode(sig); const token = encoded + '.' + sigB64; return token; } export function keyDID(pubkey) { //var MKey = new Uint8Array(MulticodecEd25519Pubkey) // var keyWithCodec = new Uint8Array(MulticodecEd25519Pubkey.length + pubkey.length); // keyWithCodec.set(MulticodecEd25519Pubkey); // keyWithCodec.set(pubkey, MulticodecEd25519Pubkey.length); const keyWithCodec = new Uint8Array([...MulticodecEd25519Pubkey, ...pubkey]); console.log('keyDID', keyWithCodec); const mb = base58btc.encode(keyWithCodec); return `did:key:${mb}`; } function objectToB64URL(o) { const s = new TextEncoder().encode(JSON.stringify(o)); return b64urlEncode(s); } function b64urlEncode(bytes) { const s = b64Encode(bytes); return s.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_'); } function b64Encode(bytes) { if (Buffer !== undefined) { return Buffer.from(bytes).toString('base64'); } return btoa(String.fromCharCode.apply(null, [...bytes])); }