Skip to content
This repository was archived by the owner on Mar 20, 2024. It is now read-only.

Commit 3ca5ff3

Browse files
authored
Merge pull request #5 from ABlockOfficial/feature_sign_message
Feature sign message
2 parents b1129ff + d8ced38 commit 3ca5ff3

File tree

6 files changed

+115
-25
lines changed

6 files changed

+115
-25
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@a-block/a-blockjs",
3-
"version": "2.0.0",
3+
"version": "2.0.1",
44
"description": "API wrapper to access the ABlock network",
55
"main": "lib/index.js",
66
"types": "lib/index.d.ts",

src/interfaces/error.interfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export enum IErrorInternal {
9292
UnableToFindNonEmptyAddresses = 'Unable to find addresses that contain assets',
9393
InvalidNetworkResponse = 'Invalid network response',
9494
UnableToSignMessage = 'Unable to sign message',
95+
UnableToVerifyMessage = 'Unable to verify message',
9596
NoHostsProvided = 'No hosts provided',
9697
NoKeypairsProvided = 'No key-pairs provided',
9798
NoPassPhraseProvided = 'No passphrase provided',

src/interfaces/success.interfaces.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ export enum ISuccessNotary {
3030

3131
export enum ISuccessInternal {
3232
ClientInitialized = 'Client initialized',
33-
MessageSigned = 'Message successfully signed',
33+
MessageSigned = 'Successfully signed message',
34+
MessageVirified = 'Successfully verified message',
3435
RbPaymentProcessing = 'Receipt-based payment processing',
3536
PendingRbPaymentsFetched = 'Succesfully fetched pending receipt-based transactions',
3637
AddressesReconstructed = 'Addresses have successfully been reconstructed',

src/services/ablock.service.ts

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,9 @@ export class ABlockWallet {
107107
/**
108108
* Initialize an instance of the client with a provided master key
109109
*
110-
* @param {IClientConfig} config - Additional configuration parameters
111110
* @param {IMasterKeyEncrypted} masterKey - Master key
111+
* @param {IClientConfig} config - Additional configuration parameters
112112
* @param initOffline - Optionally initialize the client without initializing network settings
113-
*
114113
* @return {*} {IClientResponse}
115114
* @memberof ABlockWallet
116115
*/
@@ -144,11 +143,10 @@ export class ABlockWallet {
144143
/**
145144
* Initialize an instance of the wallet with a provided seed phrase
146145
*
147-
* @param {IClientConfig} config - Additional configuration parameters
148146
* @param {string} seedPhrase - Seed phrase
147+
* @param {IClientConfig} config - Additional configuration parameters
148+
* @param initOffline - Optionally initialize the client without initializing network settings
149149
* @return {*} {IClientResponse}
150-
* @param initOffline - Optionally initialize the client without initializing network settings
151-
*
152150
* @memberof ABlockWallet
153151
*/
154152
public async fromSeed(
@@ -157,7 +155,7 @@ export class ABlockWallet {
157155
initOffline = false,
158156
): Promise<IClientResponse> {
159157
this.keyMgmt = new mgmtClient();
160-
const initIResult = this.keyMgmt.fromSeed(config.passphrase, seedPhrase);
158+
const initIResult = this.keyMgmt.fromSeed(seedPhrase, config.passphrase);
161159
if (!initOffline) {
162160
const initNetworkIResult = await this.initNetwork(config);
163161
if (initNetworkIResult.status === 'error') {
@@ -184,7 +182,7 @@ export class ABlockWallet {
184182
* Common network initialization (retrieval of PoW list for compute and storage)
185183
*
186184
* @param {IClientConfig} config - Configuration parameters
187-
*
185+
* @return {*} {IClientResponse}
188186
* @memberof ABlockWallet
189187
*/
190188
public async initNetwork(config: IClientConfig): Promise<IClientResponse> {
@@ -239,6 +237,7 @@ export class ABlockWallet {
239237
*
240238
* @private
241239
* @param {IClientConfig} config - Additional configuration parameters
240+
* @return {*} {IClientResponse}
242241
* @memberof ABlockWallet
243242
*/
244243
private async initNetworkForHost(
@@ -601,10 +600,10 @@ export class ABlockWallet {
601600
* @return {*} {Promise<IClientResponse>}
602601
* @memberof ABlockWallet
603602
*/
604-
async signMessage(
603+
signMessage(
605604
keyPairsToSignWith: IKeypairEncrypted[],
606605
message: string,
607-
): Promise<IClientResponse> {
606+
): IClientResponse {
608607
try {
609608
if (this.keyMgmt === undefined) throw new Error(IErrorInternal.ClientNotInitialized);
610609
const keyPairs = throwIfErr(this.keyMgmt.decryptKeypairs(keyPairsToSignWith));
@@ -624,6 +623,28 @@ export class ABlockWallet {
624623
}
625624
}
626625

626+
verifyMessage(
627+
message: string,
628+
signatures: IGenericKeyPair<string>,
629+
keyPairs: IKeypairEncrypted[],
630+
): IClientResponse {
631+
try {
632+
if (this.keyMgmt === undefined) throw new Error(IErrorInternal.ClientNotInitialized);
633+
const keyPairsUnencrypted = throwIfErr(this.keyMgmt.decryptKeypairs(keyPairs));
634+
throwIfErr(this.keyMgmt.verifyMessage(message, signatures, keyPairsUnencrypted));
635+
return {
636+
status: 'success',
637+
reason: ISuccessInternal.MessageVirified,
638+
} as IClientResponse;
639+
} catch (error) {
640+
return {
641+
status: 'error',
642+
reason: `${error}`,
643+
} as IClientResponse;
644+
}
645+
}
646+
647+
627648
/**
628649
* Make a payment of a specified token amount to a payment address
629650
*

src/services/mgmt.service.ts

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {
3030
TEMP_ADDRESS_VERSION,
3131
} from '../mgmt';
3232
import { concatTypedArrays, getBytesString, getStringBytes, truncateByBytesUTF8 } from '../utils';
33-
import { getBytesHexString } from '../utils/general.utils';
33+
import { getBytesHexString, getHexStringBytes } from '../utils/general.utils';
3434

3535
export class mgmtClient {
3636
private passphraseKey: Uint8Array;
@@ -80,8 +80,8 @@ export class mgmtClient {
8080
/**
8181
* Init the client with a provided master key
8282
*
83-
* @param {string} passphraseKey
8483
* @param {IMasterKeyEncrypted} masterKey
84+
* @param {string} passphraseKey
8585
* @return {*} {IResult<void>}
8686
* @memberof mgmtClient
8787
*/
@@ -99,8 +99,8 @@ export class mgmtClient {
9999
/**
100100
* Init the client with a provided seed phrase
101101
*
102-
* @param {string} passphraseKey
103102
* @param {string} seedPhrase
103+
* @param {string} passphraseKey
104104
* @return {*} {IResult<IMasterKeyEncrypted>}
105105
* @memberof mgmtClient
106106
*/
@@ -481,16 +481,27 @@ export class mgmtClient {
481481
* @memberof mgmtClient
482482
*/
483483
public signMessage(keypairs: IKeypair[], message: string): IResult<IGenericKeyPair<string>> {
484-
try {
485-
const signatures: IGenericKeyPair<string> = {};
486-
for (const keypair of keypairs) {
487-
const signature = nacl.sign.detached(Buffer.from(message), keypair.secretKey);
488-
signatures[getBytesHexString(keypair.publicKey)] = getBytesHexString(signature);
489-
}
490-
return ok(signatures);
491-
} catch {
492-
return err(IErrorInternal.UnableToSignMessage);
484+
if (keypairs.length < 1)
485+
return err(IErrorInternal.InvalidInputs);
486+
const signatures: IGenericKeyPair<string> = {};
487+
for (const keypair of keypairs) {
488+
const signature = nacl.sign.detached(Buffer.from(message), keypair.secretKey);
489+
signatures[getBytesHexString(keypair.publicKey)] = getBytesHexString(signature);
490+
}
491+
if (Object.keys(signatures).length < 1) return err(IErrorInternal.UnableToSignMessage);
492+
return ok(signatures);
493+
}
494+
495+
public verifyMessage(message: string, signatures: IGenericKeyPair<string>, keypairs: IKeypair[]): IResult<boolean> {
496+
console.log(keypairs.length, Object.keys(signatures).length)
497+
if (keypairs.length < 1 || Object.keys(signatures).length != keypairs.length)
498+
return err(IErrorInternal.InvalidInputs);
499+
for (const keypair of keypairs) {
500+
const sig = signatures[getBytesHexString(keypair.publicKey)]
501+
if (!sig || !nacl.sign.detached.verify(Buffer.from(message), getHexStringBytes(sig), keypair.publicKey))
502+
return err(IErrorInternal.UnableToVerifyMessage);
493503
}
504+
return ok(true);
494505
}
495506

496507
/**

src/tests/__tests__/ablock.service.test.ts

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ test('init wallet without optional config fields', async () => {
3333

3434
test('init wallet locally and then connect', async () => {
3535
await ablockInstance.initNew({ passphrase: '' }, true).then((res) => {
36-
console.log(res)
3736
expect(res.status).toBe('success');
3837
});
3938

@@ -44,7 +43,6 @@ test('init wallet locally and then connect', async () => {
4443
};
4544

4645
await ablockInstance.initNetwork(config).then((res) => {
47-
console.log(res)
4846
expect(res.status).toBe('success');
4947
});
5048
});
@@ -79,3 +77,61 @@ test('handles key-pair re-generation from wallet seed phrase', async () => {
7977
),
8078
).toEqual(utxoAddressList);
8179
});
80+
81+
test('sign message with given keypairs', async () => {
82+
const config = {
83+
mempoolHost: 'http://49.12.234.10:3003',
84+
passphrase: '',
85+
};
86+
const MSG = 'hello, world';
87+
88+
await ablockInstance.initNew(config).then((res) => {
89+
expect(res.status).toBe('success');
90+
});
91+
92+
const kp = ablockInstance.getNewKeypair([]).content?.newKeypairResponse;
93+
const kpAddr = kp?.address;
94+
95+
expect(kp).toBeDefined();
96+
expect(kpAddr).toBeDefined();
97+
98+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
99+
const kp1 = ablockInstance.getNewKeypair([kpAddr!]).content?.newKeypairResponse;
100+
101+
expect(kp1).toBeDefined();
102+
103+
const keypairs = [kp!, kp1!];
104+
105+
expect(keypairs).toBeDefined();
106+
107+
const signatures = ablockInstance.signMessage(keypairs, MSG).content?.signMessageResponse;
108+
109+
expect(signatures).toBeDefined();
110+
111+
const result = ablockInstance.verifyMessage(MSG, signatures!, keypairs)
112+
113+
expect(result.status).toBe('success');
114+
115+
const kp2 = ablockInstance.getNewKeypair([kpAddr!, kp1!.address]).content?.newKeypairResponse;
116+
117+
expect(kp2).toBeDefined();
118+
119+
const keypairs1 = [kp!, kp2!];
120+
121+
const result1 = ablockInstance.verifyMessage(MSG, signatures!, keypairs1)
122+
console.log('RESULT 1: ', result1)
123+
expect(result1.status).toBe('error');
124+
125+
// if (kp.content?.newKeypairResponse && kp1?.content?.newKeypairResponse)
126+
// keypairs = [kp.content.newKeypairResponse, kp1.content.newKeypairResponse];
127+
128+
// if (keypairs) {
129+
// const signatures = await ablockInstance.signMessage(keypairs, MSG);
130+
// ¨ const result = await ablockInstance.verifyMessage(MSG, signatures.content?.signMessageResponse, keypairs);
131+
// console.log(result)
132+
// }
133+
134+
// const kp = ablockInstance.getNewKeypair([]);
135+
136+
// await ablockInstance.signMessage(,)
137+
});

0 commit comments

Comments
 (0)