Skip to content

Commit

Permalink
Merge pull request #593 from airgap-it/feat/proof-of-event
Browse files Browse the repository at this point in the history
[Feat] Proof of Event
  • Loading branch information
AndreasGassmann authored Oct 18, 2023
2 parents e08e392 + f3c4633 commit e9796c1
Show file tree
Hide file tree
Showing 34 changed files with 1,130 additions and 72 deletions.
494 changes: 494 additions & 0 deletions examples/abstracted-account.html

Large diffs are not rendered by default.

45 changes: 41 additions & 4 deletions examples/dapp.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@
</span>
<br /><br />
<button id="requestPermission">Request Permission</button>
<br /><br />

<br /><br />
<button id="reset">Reset and Refresh</button>
<br /><br />

<button id="requestProofOfEventChallenge" disabled style="opacity: 0.5">
Request Proof Of Event Challenge
</button>
<br /><br />
<button id="sendToSelf">Send 1 mutez to myself</button>
<br /><br />
Expand Down Expand Up @@ -201,6 +201,7 @@
],
[beacon.Regions.NORTH_AMERICA_EAST]: []
},
preferredNetwork: beacon.NetworkType.GHOSTNET,
featuredWallets: ['airgap', 'metamask']
// network: {
// type: beacon.NetworkType.GHOSTNET
Expand All @@ -218,6 +219,16 @@
document.getElementById('activeAccount').innerText = activeAccount.address
document.getElementById('activeAccountNetwork').innerText = activeAccount.network.type
document.getElementById('activeAccountTransport').innerText = activeAccount.origin.type

if (
activeAccount.walletType !== 'account_abstracted' &&
activeAccount.verificationType !== 'proof_of_event'
)
return

const btn = document.getElementById('requestProofOfEventChallenge')
btn.style.opacity = '1'
btn.disabled = false
} else {
document.getElementById('activeAccount').innerText = ''
document.getElementById('activeAccountNetwork').innerText = ''
Expand Down Expand Up @@ -268,7 +279,7 @@
// send contract call
const sendContractCall = () => {
return client.getActiveAccount().then(async (activeAccount) => {
const TZ_BUTTON_COLORS_CONTRACT = 'KT1RPW5kTX6WFxg8JK34rGEU24gqEEudyfvz'
const TZ_BUTTON_COLORS_CONTRACT = 'KT1GSdrLzGAorWKoe2z7qV3P5Df6Vmo7neZt'
const tokenId = '925'

// Setting the color of TzButton is only possible if you are currently the leader and own a color
Expand Down Expand Up @@ -313,6 +324,27 @@
})
}

// Initiate a Proof Of Event Request
const requestProofOfEventChallenge = () => {
client
.requestProofOfEventChallenge({
dAppChallengeId: 'my-id',
payload: JSON.stringify({ timestamp: Date.now() })
})
.then(() => {
console.log('ProofOfEventChallenge approved')

const promise = client.getProofOfEventChallenge('my-id')

promise.then(() => {
alert('Proof of event verified')
})
})
.catch((error) => {
console.log('error during Proof Of Event Challenge', error)
})
}

document.getElementById('connect').addEventListener('click', () => {
// Check if we have an active account
client.getActiveAccount().then((activeAccount) => {
Expand All @@ -339,6 +371,11 @@
requestPermission()
})

// Add event listener to the button
document.getElementById('requestProofOfEventChallenge').addEventListener('click', () => {
requestProofOfEventChallenge()
})

// Add event listener to the button
document.getElementById('reset').addEventListener('click', () => {
client.destroy().then(() => {
Expand Down
7 changes: 4 additions & 3 deletions examples/index.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<a href="dapp.html">DApp</a><br /><a href="wallet.html">Wallet</a><br /><a href="events.html"
>Events</a
>
<a href="dapp.html">DApp</a><br />
<a href="wallet.html">Wallet</a><br />
<a href="events.html">Events</a><br />
<a href="abstracted-account.html">Abstracted account</a><br />
31 changes: 26 additions & 5 deletions packages/beacon-core/__tests__/managers/AccountManager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ const account1: AccountInfo = {
type: Origin.P2P,
id: 'o1'
},
address: 'tz1',
publicKey: 'pubkey1',
address: 'KT1',
network: { type: NetworkType.MAINNET },
scopes: [PermissionScope.SIGN],
connectedAt: new Date().getTime()
connectedAt: new Date().getTime(),
walletType: 'abstracted_account',
hasVerifiedChallenge: false
}

const account2: AccountInfo = {
Expand All @@ -35,7 +36,8 @@ const account2: AccountInfo = {
publicKey: 'pubkey2',
network: { type: NetworkType.MAINNET },
scopes: [PermissionScope.SIGN],
connectedAt: new Date().getTime()
connectedAt: new Date().getTime(),
walletType: 'implicit'
}

const account3: AccountInfo = {
Expand All @@ -49,7 +51,8 @@ const account3: AccountInfo = {
publicKey: 'pubkey3',
network: { type: NetworkType.MAINNET },
scopes: [PermissionScope.SIGN],
connectedAt: new Date().getTime()
connectedAt: new Date().getTime(),
walletType: 'implicit'
}

describe(`AccountManager`, () => {
Expand Down Expand Up @@ -87,6 +90,24 @@ describe(`AccountManager`, () => {
expect(accountsAfterReplacing[0].scopes, 'after replacing').to.deep.equal(newAccount1.scopes)
})

it(`updates an existing account`, async () => {
const accountsBefore: AccountInfo[] = await manager.getAccounts()
expect(accountsBefore.length, 'before').to.equal(0)

await manager.addAccount(account1)
const accountsAfterAdding: AccountInfo[] = await manager.getAccounts()

expect(accountsAfterAdding.length, 'after adding').to.equal(1)

await manager.updateAccount(account1.accountIdentifier, {
hasVerifiedChallenge: true
})
const accountsAfterReplacing: AccountInfo[] = await manager.getAccounts()

expect(accountsAfterReplacing.length, 'after replacing').to.equal(1)
expect(accountsAfterReplacing[0].hasVerifiedChallenge, 'after replacing').to.equal(true)
})

it(`reads and adds multiple accounts`, async () => {
const accountsBefore: AccountInfo[] = await manager.getAccounts()
expect(accountsBefore.length, 'before').to.equal(0)
Expand Down
18 changes: 18 additions & 0 deletions packages/beacon-core/src/managers/AccountManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,24 @@ export class AccountManager {
)
}

public async updateAccount(
accountIdentifier: string,
accountInfo: Partial<AccountInfo>
): Promise<AccountInfo | undefined> {
const account = await this.getAccount(accountIdentifier)

if (!account) return undefined

const newAccount = { ...account, ...accountInfo }
await this.storageManager.addOne(
newAccount,
(account) => account.accountIdentifier === accountIdentifier,
true
)

return newAccount
}

public async removeAccount(accountIdentifier: string): Promise<void> {
return this.storageManager.remove((account) => account.accountIdentifier === accountIdentifier)
}
Expand Down
86 changes: 75 additions & 11 deletions packages/beacon-dapp/__tests__/dapp-client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import {
StorageKey,
TezosOperationType,
TransportStatus,
ExtendedP2PPairingRequest
ExtendedP2PPairingRequest,
ProofOfEventChallengeResponse
} from '@airgap/beacon-types'

import { MockTransport } from '../../../test/test-utils/MockTransport'
Expand Down Expand Up @@ -71,11 +72,13 @@ const account1: AccountInfo = {
type: Origin.P2P,
id: peer1.publicKey
},
address: 'tz1',
publicKey: 'pubkey1',
address: 'KT1',
network: { type: NetworkType.MAINNET },
scopes: [PermissionScope.SIGN],
connectedAt: new Date().getTime()
connectedAt: new Date().getTime(),
walletType: 'abstracted_account',
verificationType: 'proof_of_event',
hasVerifiedChallenge: false
}

const account2: AccountInfo = {
Expand All @@ -89,7 +92,8 @@ const account2: AccountInfo = {
publicKey: 'pubkey2',
network: { type: NetworkType.MAINNET },
scopes: [PermissionScope.SIGN],
connectedAt: new Date().getTime()
connectedAt: new Date().getTime(),
walletType: 'implicit'
}

/**
Expand Down Expand Up @@ -161,7 +165,8 @@ describe(`DAppClient`, () => {
type: BeaconMessageType.PermissionResponse,
publicKey: 'pubkey1',
network: { type: NetworkType.MAINNET },
scopes: []
scopes: [],
walletType: 'implicit'
}
const contextInfo: ConnectionContext = {
origin: Origin.P2P,
Expand Down Expand Up @@ -317,7 +322,8 @@ describe(`DAppClient`, () => {
publicKey: 'pubkey1',
network: { type: NetworkType.MAINNET },
scopes: [PermissionScope.SIGN],
connectedAt: new Date().getTime()
connectedAt: new Date().getTime(),
walletType: 'implicit'
}

const getPeersStub = sinon.stub(DAppClient.prototype, <any>'getPeer').resolves(peer1)
Expand Down Expand Up @@ -565,7 +571,8 @@ describe(`DAppClient`, () => {
senderId: 'sender-id',
publicKey: '444e1f4ab90c304a5ac003d367747aab63815f583ff2330ce159d12c1ecceba1',
network: { type: NetworkType.MAINNET },
scopes: [PermissionScope.SIGN, PermissionScope.OPERATION_REQUEST]
scopes: [PermissionScope.SIGN, PermissionScope.OPERATION_REQUEST],
walletType: 'implicit'
}

const connectionInfo: ConnectionContext = {
Expand Down Expand Up @@ -622,6 +629,60 @@ describe(`DAppClient`, () => {
})
})

it(`should prepare a proof of event challenge request`, async () => {
const dAppClient = new DAppClient({ name: 'Test', storage: new LocalStorage() })

const permissionResponse: ProofOfEventChallengeResponse = {
id: 'my-id',
type: BeaconMessageType.ProofOfEventChallengeResponse,
version: BEACON_VERSION,
senderId: 'sender-id',
dAppChallengeId: 'my-id',
isAccepted: true
}

const connectionInfo: ConnectionContext = {
origin: Origin.P2P,
id: 'KT1'
}
const makeRequestStub = sinon
.stub(dAppClient, <any>'makeRequest')
.resolves({ message: permissionResponse, connectionInfo })

const notifySuccessStub = sinon.stub(dAppClient, <any>'notifySuccess').resolves()

const recordProofOfEventChallengeStub = sinon
.stub(dAppClient, <any>'recordProofOfEventChallenge')
.resolves()

const getActiveAccountStub = sinon.stub(dAppClient, <any>'getActiveAccount').resolves(account1)

const input = {
dAppChallengeId: 'my-id',
payload: 'my-payload'
}
const response = await dAppClient.requestProofOfEventChallenge(input)

expect(notifySuccessStub.callCount, 'notifySuccessStub').to.equal(1)
expect(recordProofOfEventChallengeStub.callCount, 'recordProofOfEventChallengeStub').to.equal(1)
expect(getActiveAccountStub.callCount, 'getActiveAccountStub').to.equal(2)
expect(makeRequestStub.callCount).to.equal(1)
expect(makeRequestStub.firstCall.args[0]).to.deep.equal({
type: BeaconMessageType.ProofOfEventChallengeRequest,
contractAddress: 'KT1',
...input
})
delete (response as any).accountInfo
expect(response).to.deep.equal({
id: 'my-id',
type: 'proof_of_event_challenge_response',
version: BEACON_VERSION,
senderId: 'sender-id',
dAppChallengeId: 'my-id',
isAccepted: true
})
})

it(`should prepare a sign payload request (RAW)`, async () => {
const dAppClient = new DAppClient({ name: 'Test', storage: new LocalStorage() })

Expand All @@ -637,7 +698,8 @@ describe(`DAppClient`, () => {
network: { type: NetworkType.MAINNET },
scopes: [PermissionScope.SIGN, PermissionScope.OPERATION_REQUEST],
threshold: undefined,
connectedAt: 1599142450653
connectedAt: 1599142450653,
walletType: 'implicit'
}

const getPeerStub = sinon.stub(DAppClient.prototype, <any>'getPeer').resolves(peer1)
Expand Down Expand Up @@ -739,7 +801,8 @@ describe(`DAppClient`, () => {
network: { type: NetworkType.MAINNET },
scopes: [PermissionScope.SIGN, PermissionScope.OPERATION_REQUEST],
threshold: undefined,
connectedAt: 1599142450653
connectedAt: 1599142450653,
walletType: 'implicit'
}

const getPeerStub = sinon.stub(DAppClient.prototype, <any>'getPeer').resolves(peer1)
Expand Down Expand Up @@ -807,7 +870,8 @@ describe(`DAppClient`, () => {
network: { type: NetworkType.MAINNET },
scopes: [PermissionScope.SIGN, PermissionScope.OPERATION_REQUEST],
threshold: undefined,
connectedAt: 1599142450653
connectedAt: 1599142450653,
walletType: 'implicit'
}

const getPeerStub = sinon.stub(DAppClient.prototype, <any>'getPeer').resolves(peer1)
Expand Down
15 changes: 15 additions & 0 deletions packages/beacon-dapp/src/beacon-message-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@ export const messageEvents: {
success: BeaconEvent.UNKNOWN,
error: BeaconEvent.UNKNOWN
},
[BeaconMessageType.ProofOfEventChallengeRequest]: {
sent: BeaconEvent.PROOF_OF_EVENT_CHALLENGE_REQUEST_SENT,
success: BeaconEvent.PROOF_OF_EVENT_CHALLENGE_REQUEST_SUCCESS,
error: BeaconEvent.PROOF_OF_EVENT_CHALLENGE_REQUEST_ERROR
},
[BeaconMessageType.ProofOfEventChallengeResponse]: {
sent: BeaconEvent.UNKNOWN,
success: BeaconEvent.UNKNOWN,
error: BeaconEvent.UNKNOWN
},
[BeaconMessageType.ProofOfEventChallengeRecorded]: {
sent: BeaconEvent.UNKNOWN,
success: BeaconEvent.UNKNOWN,
error: BeaconEvent.UNKNOWN
},
[BeaconMessageType.OperationRequest]: {
sent: BeaconEvent.OPERATION_REQUEST_SENT,
success: BeaconEvent.OPERATION_REQUEST_SUCCESS,
Expand Down
Loading

0 comments on commit e9796c1

Please sign in to comment.