wallet-storage
Version:
BRC100 conforming wallet, wallet storage and wallet signer components
174 lines (147 loc) • 7.27 kB
text/typescript
import { AcquireCertificateArgs, CompletedProtoWallet, ProveCertificateArgs } from '@bsv/sdk'
import { _tu, expectToThrowWERR } from "../../utils/TestUtilsWalletStorage"
import { sdk, Wallet } from '../../../src/index.all'
describe('acquireCertificate tests', () => {
jest.setTimeout(99999999)
const env = _tu.getEnv('test')
beforeAll(async () => {
})
afterAll(async () => {
})
test('1 invalid params', async () => {
const { wallet, storage } = await _tu.createLegacyWalletSQLiteCopy('acquireCertificate1')
const invalidArgs: AcquireCertificateArgs[] = [
{
type: "",
certifier: "",
acquisitionProtocol: "direct",
fields: {}
}
// Oh so many things to test...
]
for (const args of invalidArgs) {
await expectToThrowWERR(sdk.WERR_INVALID_PARAMETER, () => wallet.acquireCertificate(args))
}
await storage.destroy()
})
test('2 acquireCertificate listCertificate proveCertificate', async () => {
const { wallet, storage } = await _tu.createSQLiteTestWallet({ databaseName: 'acquireCertificate2', dropAll: true })
// Make a test certificate from a random certifier for the wallet's identityKey
const subject = wallet.keyDeriver.identityKey
const { cert, certifier } = _tu.makeSampleCert(subject)
// Act as the certifier: create a wallet for them...
const certifierWallet = new CompletedProtoWallet(certifier)
// load the plaintext certificate into a CertOps object
const co = new sdk.CertOps(certifierWallet, cert)
// encrypt and sign the certificate
await co.encryptAndSignNewCertificate()
// export the signed certificate and a keyring for this wallet's identity as counterparty
const { certificate: c, keyring: kr } = co.exportForSubject()
// args object to create a new certificate via 'direct' protocol.
const args: AcquireCertificateArgs = {
serialNumber: c.serialNumber,
signature: c.signature,
privileged: false,
privilegedReason: undefined,
type: c.type,
certifier: c.certifier,
acquisitionProtocol: "direct",
fields: c.fields,
keyringForSubject: kr,
keyringRevealer: 'certifier',
revocationOutpoint: c.revocationOutpoint
}
// store the new signed certificate in user's wallet
const r = await wallet.acquireCertificate(args)
expect(r.serialNumber).toBe(c.serialNumber)
// Attempt to retrieve it... since
// the certifier is random this should
// always be unique :-)
const lcs = await wallet.listCertificates({
certifiers: [cert.certifier],
types: []
})
expect(lcs.certificates.length).toBe(1)
const lc = lcs.certificates[0]
// the result should be encrypted.
expect(lc.fields['name']).not.toBe('Alice')
// Use proveCertificate to obtain a decryption keyring:
const pkrArgs: ProveCertificateArgs = {
certificate: { serialNumber: lc.serialNumber },
fieldsToReveal: ['name'],
verifier: subject
}
const pkr = await wallet.proveCertificate(pkrArgs)
const co2 = await sdk.CertOps.fromCounterparty(wallet, { certificate: lc, keyring: pkr.keyringForVerifier, counterparty: pkrArgs.verifier })
expect(co2._decryptedFields!['name']).toBe('Alice')
const certs = await wallet.listCertificates({ types: [], certifiers: [] })
for (const cert of certs.certificates) {
const rr = await wallet.relinquishCertificate({ type: cert.type, serialNumber: cert.serialNumber, certifier: cert.certifier })
expect(rr.relinquished).toBe(true)
}
await storage.destroy()
})
test('3 privileged acquireCertificate listCertificate proveCertificate', async () => {
const { wallet, storage } = await _tu.createSQLiteTestWallet({
databaseName: 'acquireCertificate3',
privKeyHex: '42'.repeat(32),
dropAll: true
})
// Make a test certificate from a random certifier for the wallet's identityKey
// Certificate issued to the privileged key must use the privilegedKeyManager's identityKey
const subject = (await wallet.privilegedKeyManager!.getPublicKey({ identityKey: true })).publicKey
const { cert, certifier } = _tu.makeSampleCert(subject)
// Act as the certifier: create a wallet for them...
const certifierWallet = new CompletedProtoWallet(certifier)
// load the plaintext certificate into a CertOps object
const co = new sdk.CertOps(certifierWallet, cert)
// encrypt and sign the certificate
await co.encryptAndSignNewCertificate()
// export the signed certificate and a keyring for this wallet's identity as counterparty
const { certificate: c, keyring: kr } = co.exportForSubject()
// args object to create a new certificate via 'direct' protocol.
const args: AcquireCertificateArgs = {
serialNumber: c.serialNumber,
signature: c.signature,
privileged: true,
privilegedReason: 'access to my penthouse',
type: c.type,
certifier: c.certifier,
acquisitionProtocol: "direct",
fields: c.fields,
keyringForSubject: kr,
keyringRevealer: 'certifier',
revocationOutpoint: c.revocationOutpoint
}
// store the new signed certificate in user's wallet
const r = await wallet.acquireCertificate(args)
expect(r.serialNumber).toBe(c.serialNumber)
// Attempt to retrieve it... since
// the certifier is random this should
// always be unique :-)
const lcs = await wallet.listCertificates({
certifiers: [cert.certifier],
types: []
})
expect(lcs.certificates.length).toBe(1)
const lc = lcs.certificates[0]
// the result should be encrypted.
expect(lc.fields['name']).not.toBe('Alice')
// Use proveCertificate to obtain a decryption keyring:
const pkrArgs: ProveCertificateArgs = {
certificate: { serialNumber: lc.serialNumber },
fieldsToReveal: ['name'],
verifier: subject
}
const pkr = await wallet.proveCertificate(pkrArgs)
const co2 = await sdk.CertOps.fromCounterparty(wallet.privilegedKeyManager!, { certificate: lc, keyring: pkr.keyringForVerifier, counterparty: pkrArgs.verifier })
expect(co2._decryptedFields!['name']).toBe('Alice')
const certs = await wallet.listCertificates({ types: [], certifiers: [] })
for (const cert of certs.certificates) {
const rr = await wallet.relinquishCertificate({ type: cert.type, serialNumber: cert.serialNumber, certifier: cert.certifier })
expect(rr.relinquished).toBe(true)
}
// Also cleans up the privilegedKeyManager
await wallet.destroy()
})
})