diff --git a/web3.js/src/publickey.js b/web3.js/src/publickey.js index eda451614c..9f29aceebd 100644 --- a/web3.js/src/publickey.js +++ b/web3.js/src/publickey.js @@ -78,7 +78,7 @@ export class PublicKey { } /** - * Derive a public key from another key, a seed, and a programId. + * Derive a public key from another key, a seed, and a program ID. */ static async createWithSeed( fromPublicKey: PublicKey, @@ -93,4 +93,25 @@ export class PublicKey { const hash = await sha256(new Uint8Array(buffer)); return new PublicKey('0x' + hash); } + + /** + * Derive a program address from seeds and a program ID. + */ + static async createProgramAddress( + seeds: Array, + programId: PublicKey, + ): Promise { + let buffer = Buffer.alloc(0); + seeds.forEach(function (seed) { + buffer = Buffer.concat([buffer, Buffer.from(seed)]); + }); + buffer = Buffer.concat([ + buffer, + programId.toBuffer(), + Buffer.from('ProgramDerivedAddress'), + ]); + let hash = await sha256(new Uint8Array(buffer)); + hash = await sha256(new Uint8Array(new BN(hash, 16).toBuffer())); + return new PublicKey('0x' + hash); + } } diff --git a/web3.js/test/publickey.test.js b/web3.js/test/publickey.test.js index b66fba51af..faeb2ae2d5 100644 --- a/web3.js/test/publickey.test.js +++ b/web3.js/test/publickey.test.js @@ -238,3 +238,40 @@ test('createWithSeed', async () => { ), ).toBe(true); }); + +test('createProgramAddress', async () => { + const programId = new PublicKey( + 'BPFLoader1111111111111111111111111111111111', + ); + + let programAddress = await PublicKey.createProgramAddress([''], programId); + expect( + programAddress.equals( + new PublicKey('CsdSsqp6Upkh2qajhZMBM8xT4GAyDNSmcV37g4pN8rsc'), + ), + ).toBe(true); + programAddress = await PublicKey.createProgramAddress(['☉'], programId); + expect( + programAddress.equals( + new PublicKey('A8mYnN8Pfx7Nn6f8RoQgsPNtAGAWmmKSBCDfyDvE6sXF'), + ), + ).toBe(true); + programAddress = await PublicKey.createProgramAddress( + ['Talking', 'Squirrels'], + programId, + ); + expect( + programAddress.equals( + new PublicKey('CawYq8Rmj4JRR992wVnGEFUjMEkmtmcFgEL4iS1qPczu'), + ), + ).toBe(true); + programAddress = await PublicKey.createProgramAddress( + ['Talking', 'Squirrels'], + programId, + ); + const programAddress2 = await PublicKey.createProgramAddress( + ['Talking'], + programId, + ); + expect(programAddress.equals(programAddress2)).toBe(false); +});