feat: support user-supplied Token programs

This commit is contained in:
Michael Vines
2018-10-18 09:28:21 -07:00
parent a9fc62d891
commit 00fd0fc435
3 changed files with 33 additions and 25 deletions

View File

@ -119,7 +119,7 @@ declare module '@solana/web3.js' {
declare type TokenAndPublicKey = [Token, PublicKey]; declare type TokenAndPublicKey = [Token, PublicKey];
declare export class Token { declare export class Token {
static programId: PublicKey; programId: PublicKey;
token: PublicKey; token: PublicKey;
static createNewToken( static createNewToken(

View File

@ -134,6 +134,12 @@ const TokenAccountInfoLayout = BufferLayout.struct([
type TokenAndPublicKey = [Token, PublicKey]; // This type exists to workaround an esdoc parse error type TokenAndPublicKey = [Token, PublicKey]; // This type exists to workaround an esdoc parse error
/**
* The built-in token program
*/
export const SYSTEM_TOKEN_PROGRAM_ID = new PublicKey('0x500000000000000000000000000000000000000000000000000000000000000');
/** /**
* An ERC20-like Token * An ERC20-like Token
*/ */
@ -149,14 +155,20 @@ export class Token {
*/ */
token: PublicKey; token: PublicKey;
/**
* Program Identifier for the Token program
*/
programId: PublicKey;
/** /**
* Create a Token object attached to the specific token * Create a Token object attached to the specific token
* *
* @param connection The connection to use * @param connection The connection to use
* @param token Public key of the token * @param token Public key of the token
* @param programId Optional token programId, uses the system programId by default
*/ */
constructor(connection: Connection, token: PublicKey) { constructor(connection: Connection, token: PublicKey, programId: PublicKey = SYSTEM_TOKEN_PROGRAM_ID) {
Object.assign(this, {connection, token}); Object.assign(this, {connection, token, programId});
} }
/** /**
@ -168,6 +180,7 @@ export class Token {
* @param name Descriptive name of this token * @param name Descriptive name of this token
* @param symbol Symbol for this token * @param symbol Symbol for this token
* @param decimals Location of the decimal place * @param decimals Location of the decimal place
* @param programId Optional token programId, uses the system programId by default
* @return Token object for the newly minted token, Public key of the Token Account holding the total supply of new tokens * @return Token object for the newly minted token, Public key of the Token Account holding the total supply of new tokens
*/ */
static async createNewToken( static async createNewToken(
@ -177,6 +190,7 @@ export class Token {
name: string, name: string,
symbol: string, symbol: string,
decimals: number, decimals: number,
programId: PublicKey = SYSTEM_TOKEN_PROGRAM_ID,
): Promise<TokenAndPublicKey> { ): Promise<TokenAndPublicKey> {
const tokenAccount = new Account(); const tokenAccount = new Account();
const token = new Token(connection, tokenAccount.publicKey); const token = new Token(connection, tokenAccount.publicKey);
@ -213,14 +227,14 @@ export class Token {
tokenAccount.publicKey, tokenAccount.publicKey,
1, 1,
1 + userdata.length, 1 + userdata.length,
Token.programId, programId,
); );
await sendAndConfirmTransaction(connection, owner, transaction); await sendAndConfirmTransaction(connection, owner, transaction);
transaction = new Transaction({ transaction = new Transaction({
fee: 0, fee: 0,
keys: [tokenAccount.publicKey, initialAccountPublicKey], keys: [tokenAccount.publicKey, initialAccountPublicKey],
programId: Token.programId, programId,
userdata, userdata,
}); });
await sendAndConfirmTransaction(connection, tokenAccount, transaction); await sendAndConfirmTransaction(connection, tokenAccount, transaction);
@ -253,7 +267,7 @@ export class Token {
tokenAccount.publicKey, tokenAccount.publicKey,
1, 1,
1 + TokenAccountInfoLayout.span, 1 + TokenAccountInfoLayout.span,
Token.programId, this.programId,
); );
await sendAndConfirmTransaction(this.connection, owner, transaction); await sendAndConfirmTransaction(this.connection, owner, transaction);
@ -265,7 +279,7 @@ export class Token {
transaction = new Transaction({ transaction = new Transaction({
fee: 0, fee: 0,
keys, keys,
programId: Token.programId, programId: this.programId,
userdata, userdata,
}); });
await sendAndConfirmTransaction(this.connection, tokenAccount, transaction); await sendAndConfirmTransaction(this.connection, tokenAccount, transaction);
@ -292,7 +306,7 @@ export class Token {
*/ */
async tokenInfo(): Promise<TokenInfo> { async tokenInfo(): Promise<TokenInfo> {
const accountInfo = await this.connection.getAccountInfo(this.token); const accountInfo = await this.connection.getAccountInfo(this.token);
if (!accountInfo.programId.equals(Token.programId)) { if (!accountInfo.programId.equals(this.programId)) {
throw new Error(`Invalid token programId: ${JSON.stringify(accountInfo.programId)}`); throw new Error(`Invalid token programId: ${JSON.stringify(accountInfo.programId)}`);
} }
@ -314,7 +328,7 @@ export class Token {
*/ */
async accountInfo(account: PublicKey): Promise<TokenAccountInfo> { async accountInfo(account: PublicKey): Promise<TokenAccountInfo> {
const accountInfo = await this.connection.getAccountInfo(account); const accountInfo = await this.connection.getAccountInfo(account);
if (!accountInfo.programId.equals(Token.programId)) { if (!accountInfo.programId.equals(this.programId)) {
throw new Error(`Invalid token account programId`); throw new Error(`Invalid token account programId`);
} }
@ -384,7 +398,7 @@ export class Token {
const transaction = new Transaction({ const transaction = new Transaction({
fee: 0, fee: 0,
keys, keys,
programId: Token.programId, programId: this.programId,
userdata, userdata,
}); });
await sendAndConfirmTransaction(this.connection, owner, transaction); await sendAndConfirmTransaction(this.connection, owner, transaction);
@ -422,7 +436,7 @@ export class Token {
const transaction = new Transaction({ const transaction = new Transaction({
fee: 0, fee: 0,
keys: [owner.publicKey, source, delegate], keys: [owner.publicKey, source, delegate],
programId: Token.programId, programId: this.programId,
userdata, userdata,
}); });
await sendAndConfirmTransaction(this.connection, owner, transaction); await sendAndConfirmTransaction(this.connection, owner, transaction);
@ -442,13 +456,6 @@ export class Token {
): Promise<void> { ): Promise<void> {
return this.approve(owner, source, delegate, 0); return this.approve(owner, source, delegate, 0);
} }
/**
* Program Identifier for the Token program
*/
static get programId(): PublicKey {
return new PublicKey('0x500000000000000000000000000000000000000000000000000000000000000');
}
} }

View File

@ -6,6 +6,7 @@ import {
Token, Token,
TokenAmount, TokenAmount,
} from '../src'; } from '../src';
import {SYSTEM_TOKEN_PROGRAM_ID} from '../src/token-program';
import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch'; import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch';
import {url} from './url'; import {url} from './url';
import {newAccountWithTokens} from './new-account-with-tokens'; import {newAccountWithTokens} from './new-account-with-tokens';
@ -111,7 +112,7 @@ test('create new token', async () => {
{ {
error: null, error: null,
result: { result: {
program_id: [...Token.programId.toBuffer()], program_id: [...SYSTEM_TOKEN_PROGRAM_ID.toBuffer()],
tokens: 1, tokens: 1,
userdata: [ userdata: [
1, 1,
@ -149,7 +150,7 @@ test('create new token', async () => {
{ {
error: null, error: null,
result: { result: {
program_id: [...Token.programId.toBuffer()], program_id: [...SYSTEM_TOKEN_PROGRAM_ID.toBuffer()],
tokens: 1, tokens: 1,
userdata: [ userdata: [
2, 2,
@ -206,7 +207,7 @@ test('create new token account', async () => {
{ {
error: null, error: null,
result: { result: {
program_id: [...Token.programId.toBuffer()], program_id: [...SYSTEM_TOKEN_PROGRAM_ID.toBuffer()],
tokens: 1, tokens: 1,
userdata: [ userdata: [
2, 2,
@ -263,7 +264,7 @@ test('transfer', async () => {
{ {
error: null, error: null,
result: { result: {
program_id: [...Token.programId.toBuffer()], program_id: [...SYSTEM_TOKEN_PROGRAM_ID.toBuffer()],
tokens: 1, tokens: 1,
userdata: [ userdata: [
2, 2,
@ -305,7 +306,7 @@ test('transfer', async () => {
{ {
error: null, error: null,
result: { result: {
program_id: [...Token.programId.toBuffer()], program_id: [...SYSTEM_TOKEN_PROGRAM_ID.toBuffer()],
tokens: 1, tokens: 1,
userdata: [ userdata: [
2, 2,
@ -371,7 +372,7 @@ test('approve/revoke', async () => {
{ {
error: null, error: null,
result: { result: {
program_id: [...Token.programId.toBuffer()], program_id: [...SYSTEM_TOKEN_PROGRAM_ID.toBuffer()],
tokens: 1, tokens: 1,
userdata: [ userdata: [
2, 2,
@ -426,7 +427,7 @@ test('approve/revoke', async () => {
{ {
error: null, error: null,
result: { result: {
program_id: [...Token.programId.toBuffer()], program_id: [...SYSTEM_TOKEN_PROGRAM_ID.toBuffer()],
tokens: 1, tokens: 1,
userdata: [ userdata: [
2, 2,