@solana/spl-token
Advanced tools
Comparing version 0.1.0 to 0.1.1
@@ -44,2 +44,5 @@ 'use strict'; | ||
const TOKEN_PROGRAM_ID = new web3_js.PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'); | ||
const ASSOCIATED_TOKEN_PROGRAM_ID = new web3_js.PublicKey('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL'); | ||
const FAILED_TO_FIND_ACCOUNT = 'Failed to find account'; | ||
const INVALID_ACCOUNT_OWNER = 'Invalid account owner'; | ||
/** | ||
@@ -141,2 +144,6 @@ * Unfortunately, BufferLayout.encode uses an `instanceof` check for `Buffer` | ||
/** | ||
* Program Identifier for the Associated Token program | ||
*/ | ||
/** | ||
* Fee payer | ||
@@ -160,2 +167,4 @@ */ | ||
_defineProperty__default['default'](this, "associatedProgramId", void 0); | ||
_defineProperty__default['default'](this, "payer", void 0); | ||
@@ -167,3 +176,5 @@ | ||
programId, | ||
payer | ||
payer, | ||
// Hard code is ok; Overriding is needed only for tests | ||
associatedProgramId: ASSOCIATED_TOKEN_PROGRAM_ID | ||
}); | ||
@@ -261,2 +272,60 @@ } | ||
/** | ||
* Create and initialize the associated account. | ||
* | ||
* This account may then be used as a `transfer()` or `approve()` destination | ||
* | ||
* @param owner User account that will own the new account | ||
* @return Public key of the new associated account | ||
*/ | ||
async createAssociatedTokenAccount(owner) { | ||
const associatedAddress = await Token.getAssociatedTokenAddress(this.associatedProgramId, this.programId, this.publicKey, owner); | ||
return this.createAssociatedTokenAccountInternal(owner, associatedAddress); | ||
} | ||
async createAssociatedTokenAccountInternal(owner, associatedAddress) { | ||
await sendAndConfirmTransaction('CreateAssociatedTokenAccount', this.connection, new web3_js.Transaction().add(Token.createAssociatedTokenAccountInstruction(this.associatedProgramId, this.programId, this.publicKey, associatedAddress, owner, this.payer.publicKey)), this.payer); | ||
return associatedAddress; | ||
} | ||
/** | ||
* Retrieve the associated account or create one if not found. | ||
* | ||
* This account may then be used as a `transfer()` or `approve()` destination | ||
* | ||
* @param owner User account that will own the new account | ||
* @return The new associated account | ||
*/ | ||
async getOrCreateAssociatedAccountInfo(owner) { | ||
const associatedAddress = await Token.getAssociatedTokenAddress(this.associatedProgramId, this.programId, this.publicKey, owner); // This is the optimum logic, considering TX fee, client-side computation, | ||
// RPC roundtrips and guaranteed idempotent. | ||
// Sadly we can't do this atomically; | ||
try { | ||
return await this.getAccountInfo(associatedAddress); | ||
} catch (err) { | ||
// INVALID_ACCOUNT_OWNER can be possible if the associatedAddress has | ||
// already been received some lamports (= became system accounts). | ||
// Assuming program derived addressing is safe, this is the only case | ||
// for the INVALID_ACCOUNT_OWNER in this code-path | ||
if (err.message === FAILED_TO_FIND_ACCOUNT || err.message === INVALID_ACCOUNT_OWNER) { | ||
// as this isn't atomic, it's possible others can create associated | ||
// accounts meanwhile | ||
try { | ||
await this.createAssociatedTokenAccountInternal(owner, associatedAddress); | ||
} catch (err) {// ignore all errors; for now there is no API compatible way to | ||
// selectively ignore the expected instruction error if the | ||
// associated account is existing already. | ||
} // Now this should always succeed | ||
return await this.getAccountInfo(associatedAddress); | ||
} else { | ||
throw err; | ||
} | ||
} | ||
} | ||
/** | ||
* Create and initialize a new account on the special native token mint. | ||
@@ -410,7 +479,7 @@ * | ||
if (info === null) { | ||
throw new Error('Failed to find account'); | ||
throw new Error(FAILED_TO_FIND_ACCOUNT); | ||
} | ||
if (!info.owner.equals(this.programId)) { | ||
throw new Error("Invalid account owner"); | ||
throw new Error(INVALID_ACCOUNT_OWNER); | ||
} | ||
@@ -424,2 +493,3 @@ | ||
const accountInfo = AccountLayout.decode(data); | ||
accountInfo.address = account; | ||
accountInfo.mint = new web3_js.PublicKey(accountInfo.mint); | ||
@@ -1616,5 +1686,70 @@ accountInfo.owner = new web3_js.PublicKey(accountInfo.owner); | ||
} | ||
/** | ||
* Get the address for the associated token account | ||
* | ||
* @param associatedProgramId SPL Associated Token program account | ||
* @param programId SPL Token program account | ||
* @param mint Token mint account | ||
* @param owner Owner of the new account | ||
* @return Public key of the associated token account | ||
*/ | ||
static async getAssociatedTokenAddress(associatedProgramId, programId, mint, owner) { | ||
return (await web3_js.PublicKey.findProgramAddress([owner.toBuffer(), programId.toBuffer(), mint.toBuffer()], associatedProgramId))[0]; | ||
} | ||
/** | ||
* Construct the AssociatedTokenProgram instruction to create the associated | ||
* token account | ||
* | ||
* @param associatedProgramId SPL Associated Token program account | ||
* @param programId SPL Token program account | ||
* @param mint Token mint account | ||
* @param associatedAccount New associated account | ||
* @param owner Owner of the new account | ||
* @param payer Payer of fees | ||
*/ | ||
static createAssociatedTokenAccountInstruction(associatedProgramId, programId, mint, associatedAccount, owner, payer) { | ||
const data = buffer.Buffer.alloc(0); | ||
let keys = [{ | ||
pubkey: payer, | ||
isSigner: true, | ||
isWritable: true | ||
}, { | ||
pubkey: associatedAccount, | ||
isSigner: false, | ||
isWritable: true | ||
}, { | ||
pubkey: owner, | ||
isSigner: false, | ||
isWritable: false | ||
}, { | ||
pubkey: mint, | ||
isSigner: false, | ||
isWritable: false | ||
}, { | ||
pubkey: web3_js.SystemProgram.programId, | ||
isSigner: false, | ||
isWritable: false | ||
}, { | ||
pubkey: programId, | ||
isSigner: false, | ||
isWritable: false | ||
}, { | ||
pubkey: web3_js.SYSVAR_RENT_PUBKEY, | ||
isSigner: false, | ||
isWritable: false | ||
}]; | ||
return new web3_js.TransactionInstruction({ | ||
keys, | ||
programId: associatedProgramId, | ||
data | ||
}); | ||
} | ||
} | ||
exports.ASSOCIATED_TOKEN_PROGRAM_ID = ASSOCIATED_TOKEN_PROGRAM_ID; | ||
exports.AccountLayout = AccountLayout; | ||
@@ -1621,0 +1756,0 @@ exports.MintLayout = MintLayout; |
@@ -15,2 +15,3 @@ declare module '@solana/spl-token' { | ||
export const TOKEN_PROGRAM_ID: PublicKey; | ||
export const ASSOCIATED_TOKEN_PROGRAM_ID: PublicKey; | ||
@@ -39,2 +40,3 @@ export class u64 extends BN { | ||
export type AccountInfo = { | ||
address: PublicKey; | ||
mint: PublicKey; | ||
@@ -70,2 +72,3 @@ owner: PublicKey; | ||
programId: PublicKey; | ||
associatedProgramId: PublicKey; | ||
payer: Account; | ||
@@ -87,2 +90,8 @@ constructor( | ||
): Promise<number>; | ||
static getAssociatedTokenAddress( | ||
associatedProgramId: PublicKey, | ||
programId: PublicKey, | ||
mint: PublicKey, | ||
owner: PublicKey, | ||
): Promise<PublicKey>; | ||
static createMint( | ||
@@ -97,2 +106,3 @@ connection: Connection, | ||
createAccount(owner: PublicKey): Promise<PublicKey>; | ||
createAssociatedTokenAccount(owner: PublicKey): Promise<PublicKey>; | ||
static createWrappedNativeAccount( | ||
@@ -108,2 +118,3 @@ connection: Connection, | ||
getAccountInfo(account: PublicKey): Promise<AccountInfo>; | ||
getOrCreateAssociatedAccountInfo(owner: PublicKey): Promise<AccountInfo>; | ||
getMultisigInfo(multisig: PublicKey): Promise<MultisigInfo>; | ||
@@ -244,3 +255,11 @@ transfer( | ||
): TransactionInstruction; | ||
static createAssociatedTokenAccountInstruction( | ||
associatedProgramId: PublicKey, | ||
programId: PublicKey, | ||
mint: PublicKey, | ||
associatedAccount: PublicKey, | ||
owner: PublicKey, | ||
payer: PublicKey, | ||
): TransactionInstruction; | ||
} | ||
} |
@@ -34,2 +34,5 @@ import _defineProperty from '@babel/runtime/helpers/defineProperty'; | ||
const TOKEN_PROGRAM_ID = new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'); | ||
const ASSOCIATED_TOKEN_PROGRAM_ID = new PublicKey('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL'); | ||
const FAILED_TO_FIND_ACCOUNT = 'Failed to find account'; | ||
const INVALID_ACCOUNT_OWNER = 'Invalid account owner'; | ||
/** | ||
@@ -131,2 +134,6 @@ * Unfortunately, BufferLayout.encode uses an `instanceof` check for `Buffer` | ||
/** | ||
* Program Identifier for the Associated Token program | ||
*/ | ||
/** | ||
* Fee payer | ||
@@ -150,2 +157,4 @@ */ | ||
_defineProperty(this, "associatedProgramId", void 0); | ||
_defineProperty(this, "payer", void 0); | ||
@@ -157,3 +166,5 @@ | ||
programId, | ||
payer | ||
payer, | ||
// Hard code is ok; Overriding is needed only for tests | ||
associatedProgramId: ASSOCIATED_TOKEN_PROGRAM_ID | ||
}); | ||
@@ -251,2 +262,60 @@ } | ||
/** | ||
* Create and initialize the associated account. | ||
* | ||
* This account may then be used as a `transfer()` or `approve()` destination | ||
* | ||
* @param owner User account that will own the new account | ||
* @return Public key of the new associated account | ||
*/ | ||
async createAssociatedTokenAccount(owner) { | ||
const associatedAddress = await Token.getAssociatedTokenAddress(this.associatedProgramId, this.programId, this.publicKey, owner); | ||
return this.createAssociatedTokenAccountInternal(owner, associatedAddress); | ||
} | ||
async createAssociatedTokenAccountInternal(owner, associatedAddress) { | ||
await sendAndConfirmTransaction('CreateAssociatedTokenAccount', this.connection, new Transaction().add(Token.createAssociatedTokenAccountInstruction(this.associatedProgramId, this.programId, this.publicKey, associatedAddress, owner, this.payer.publicKey)), this.payer); | ||
return associatedAddress; | ||
} | ||
/** | ||
* Retrieve the associated account or create one if not found. | ||
* | ||
* This account may then be used as a `transfer()` or `approve()` destination | ||
* | ||
* @param owner User account that will own the new account | ||
* @return The new associated account | ||
*/ | ||
async getOrCreateAssociatedAccountInfo(owner) { | ||
const associatedAddress = await Token.getAssociatedTokenAddress(this.associatedProgramId, this.programId, this.publicKey, owner); // This is the optimum logic, considering TX fee, client-side computation, | ||
// RPC roundtrips and guaranteed idempotent. | ||
// Sadly we can't do this atomically; | ||
try { | ||
return await this.getAccountInfo(associatedAddress); | ||
} catch (err) { | ||
// INVALID_ACCOUNT_OWNER can be possible if the associatedAddress has | ||
// already been received some lamports (= became system accounts). | ||
// Assuming program derived addressing is safe, this is the only case | ||
// for the INVALID_ACCOUNT_OWNER in this code-path | ||
if (err.message === FAILED_TO_FIND_ACCOUNT || err.message === INVALID_ACCOUNT_OWNER) { | ||
// as this isn't atomic, it's possible others can create associated | ||
// accounts meanwhile | ||
try { | ||
await this.createAssociatedTokenAccountInternal(owner, associatedAddress); | ||
} catch (err) {// ignore all errors; for now there is no API compatible way to | ||
// selectively ignore the expected instruction error if the | ||
// associated account is existing already. | ||
} // Now this should always succeed | ||
return await this.getAccountInfo(associatedAddress); | ||
} else { | ||
throw err; | ||
} | ||
} | ||
} | ||
/** | ||
* Create and initialize a new account on the special native token mint. | ||
@@ -400,7 +469,7 @@ * | ||
if (info === null) { | ||
throw new Error('Failed to find account'); | ||
throw new Error(FAILED_TO_FIND_ACCOUNT); | ||
} | ||
if (!info.owner.equals(this.programId)) { | ||
throw new Error("Invalid account owner"); | ||
throw new Error(INVALID_ACCOUNT_OWNER); | ||
} | ||
@@ -414,2 +483,3 @@ | ||
const accountInfo = AccountLayout.decode(data); | ||
accountInfo.address = account; | ||
accountInfo.mint = new PublicKey(accountInfo.mint); | ||
@@ -1606,6 +1676,70 @@ accountInfo.owner = new PublicKey(accountInfo.owner); | ||
} | ||
/** | ||
* Get the address for the associated token account | ||
* | ||
* @param associatedProgramId SPL Associated Token program account | ||
* @param programId SPL Token program account | ||
* @param mint Token mint account | ||
* @param owner Owner of the new account | ||
* @return Public key of the associated token account | ||
*/ | ||
static async getAssociatedTokenAddress(associatedProgramId, programId, mint, owner) { | ||
return (await PublicKey.findProgramAddress([owner.toBuffer(), programId.toBuffer(), mint.toBuffer()], associatedProgramId))[0]; | ||
} | ||
/** | ||
* Construct the AssociatedTokenProgram instruction to create the associated | ||
* token account | ||
* | ||
* @param associatedProgramId SPL Associated Token program account | ||
* @param programId SPL Token program account | ||
* @param mint Token mint account | ||
* @param associatedAccount New associated account | ||
* @param owner Owner of the new account | ||
* @param payer Payer of fees | ||
*/ | ||
static createAssociatedTokenAccountInstruction(associatedProgramId, programId, mint, associatedAccount, owner, payer) { | ||
const data = Buffer.alloc(0); | ||
let keys = [{ | ||
pubkey: payer, | ||
isSigner: true, | ||
isWritable: true | ||
}, { | ||
pubkey: associatedAccount, | ||
isSigner: false, | ||
isWritable: true | ||
}, { | ||
pubkey: owner, | ||
isSigner: false, | ||
isWritable: false | ||
}, { | ||
pubkey: mint, | ||
isSigner: false, | ||
isWritable: false | ||
}, { | ||
pubkey: SystemProgram.programId, | ||
isSigner: false, | ||
isWritable: false | ||
}, { | ||
pubkey: programId, | ||
isSigner: false, | ||
isWritable: false | ||
}, { | ||
pubkey: SYSVAR_RENT_PUBKEY, | ||
isSigner: false, | ||
isWritable: false | ||
}]; | ||
return new TransactionInstruction({ | ||
keys, | ||
programId: associatedProgramId, | ||
data | ||
}); | ||
} | ||
} | ||
export { AccountLayout, MintLayout, NATIVE_MINT, TOKEN_PROGRAM_ID, Token, u64 }; | ||
export { ASSOCIATED_TOKEN_PROGRAM_ID, AccountLayout, MintLayout, NATIVE_MINT, TOKEN_PROGRAM_ID, Token, u64 }; | ||
//# sourceMappingURL=index.esm.js.map |
@@ -20,2 +20,3 @@ /** | ||
declare export var TOKEN_PROGRAM_ID; | ||
declare export var ASSOCIATED_TOKEN_PROGRAM_ID; | ||
declare export class u64 extends BN { | ||
@@ -41,2 +42,3 @@ toBuffer(): typeof Buffer; | ||
declare export type AccountInfo = {| | ||
address: PublicKey, | ||
mint: PublicKey, | ||
@@ -72,2 +74,3 @@ owner: PublicKey, | ||
programId: PublicKey; | ||
associatedProgramId: PublicKey; | ||
payer: Account; | ||
@@ -89,2 +92,8 @@ constructor( | ||
): Promise<number>; | ||
static getAssociatedTokenAddress( | ||
associatedProgramId: PublicKey, | ||
programId: PublicKey, | ||
mint: PublicKey, | ||
owner: PublicKey, | ||
): Promise<PublicKey>; | ||
static createMint( | ||
@@ -99,2 +108,3 @@ connection: Connection, | ||
createAccount(owner: PublicKey): Promise<PublicKey>; | ||
createAssociatedTokenAccount(owner: PublicKey): Promise<PublicKey>; | ||
static createWrappedNativeAccount( | ||
@@ -110,2 +120,3 @@ connection: Connection, | ||
getAccountInfo(account: PublicKey): Promise<AccountInfo>; | ||
getOrCreateAssociatedAccountInfo(owner: PublicKey): Promise<AccountInfo>; | ||
getMultisigInfo(multisig: PublicKey): Promise<MultisigInfo>; | ||
@@ -246,3 +257,11 @@ transfer( | ||
): TransactionInstruction; | ||
static createAssociatedTokenAccountInstruction( | ||
associatedProgramId: PublicKey, | ||
programId: PublicKey, | ||
mint: PublicKey, | ||
associatedAccount: PublicKey, | ||
owner: PublicKey, | ||
payer: PublicKey, | ||
): TransactionInstruction; | ||
} | ||
} |
{ | ||
"name": "@solana/spl-token", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"description": "SPL Token JavaScript API", | ||
@@ -59,3 +59,3 @@ "license": "MIT", | ||
"@babel/runtime": "^7.10.5", | ||
"@solana/web3.js": "^0.92.1", | ||
"@solana/web3.js": "^0.93.0", | ||
"bn.js": "^5.1.0", | ||
@@ -62,0 +62,0 @@ "buffer": "6.0.3", |
Sorry, the diff of this file is too big to display
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 too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
4523409
27650
0
270673
+ Added@solana/web3.js@0.93.0(transitive)
+ Addedsuperstruct@0.14.2(transitive)
- Removed@solana/web3.js@0.92.3(transitive)
- Removedkind-of@6.0.3(transitive)
- Removedsuperstruct@0.8.4(transitive)
- Removedtiny-invariant@1.3.3(transitive)
Updated@solana/web3.js@^0.93.0