Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat: add support for getting an account's plan #564

Merged
merged 5 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/react/w3console/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
"devDependencies": {
"@preact/preset-vite": "^2.4.0",
"@types/blueimp-md5": "^2.18.0",
"@ucanto/core": "^8.0.0",
"@ucanto/interface": "^8.0.0",
"@ucanto/core": "^9.0.0",
"@ucanto/interface": "^9.0.0",
"autoprefixer": "^10.4.13",
"postcss": "^8.4.21",
"tailwindcss": "^3.2.4",
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@
"@types/jest": "^29.4.0",
"@types/jsdom": "^20.0.1",
"@types/react": "^18.0.26",
"@ucanto/client": "^8.0.0",
"@ucanto/server": "^8.0.1",
"@ucanto/transport": "^8.0.0",
"@ucanto/client": "^9.0.0",
"@ucanto/server": "^9.0.1",
"@ucanto/transport": "^9.0.0",
"@web-std/file": "^3.0.2",
"@web3-storage/capabilities": "^7.0.0",
"@web3-storage/capabilities": "^11.1.0",
"esm": "^3.2.25",
"fake-indexeddb": "^4.0.1",
"hd-scripts": "^4.1.0",
Expand Down
7 changes: 4 additions & 3 deletions packages/keyring-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@
},
"homepage": "https://github.com/web3-storage/w3ui/tree/main/packages/keyring-core",
"dependencies": {
"@ucanto/interface": "^8.0.0",
"@ucanto/principal": "^8.0.0",
"@web3-storage/access": "^15.2.0"
"@ucanto/interface": "^9.0.0",
"@ucanto/principal": "^9.0.0",
"@web3-storage/access": "^16.3.0",
"@web3-storage/did-mailto": "^2.0.2"
},
"eslintConfig": {
"extends": [
Expand Down
39 changes: 28 additions & 11 deletions packages/keyring-core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Abilities, AgentMeta, Service } from '@web3-storage/access/types'
import type { Abilities, AgentMeta, PlanGetFailure, PlanGetSuccess, Service } from '@web3-storage/access/types'
import type {
Capability,
DID,
Expand All @@ -9,17 +9,20 @@ import type {
Delegation,
UCANOptions
} from '@ucanto/interface'
import { Agent, authorizeWaitAndClaim } from '@web3-storage/access/agent'
import { Agent as AccessAgent, authorizeWaitAndClaim, getAccountPlan } from '@web3-storage/access/agent'
import { StoreIndexedDB } from '@web3-storage/access/stores/store-indexeddb'
import * as RSASigner from '@ucanto/principal/rsa'
import * as Ucanto from '@ucanto/interface'
import * as DidMailto from '@web3-storage/did-mailto'

export { Agent, Abilities, AgentMeta, Service }
export { Abilities, AgentMeta, Service }
export const authorize = authorizeWaitAndClaim

const DB_NAME = 'w3ui'
const DB_STORE_NAME = 'keyring'
export const W3UI_ACCOUNT_LOCALSTORAGE_KEY = 'w3ui-account-email'

export type Agent = AccessAgent & { store: StoreIndexedDB }
export type PlanGetResult = Ucanto.Result<PlanGetSuccess, PlanGetFailure | Ucanto.Failure>
/**
* A Space is the core organizational structure of web3-storage,
* similar to a bucket in S3 but with some special properties.
Expand Down Expand Up @@ -101,6 +104,11 @@ export interface RegisterSpaceOpts {
provider?: DID<'web'>
}

export type Email = `${string}@${string}`
export interface Plan {
product?: DID
}

export interface KeyringContextActions {
/**
* Load the user agent and all stored data from secure storage.
Expand All @@ -119,7 +127,7 @@ export interface KeyringContextActions {
/**
* Authorize this device to act as the account linked to email.
*/
authorize: (email: `${string}@${string}`) => Promise<void>
authorize: (email: Email) => Promise<void>
/**
* Abort an ongoing account authorization.
*/
Expand All @@ -136,7 +144,7 @@ export interface KeyringContextActions {
* Register the current space and store in secure storage. Automatically sets the
* newly registered space as the current space.
*/
registerSpace: (email: string, opts?: RegisterSpaceOpts) => Promise<void>
registerSpace: (email: Email, opts?: RegisterSpaceOpts) => Promise<void>
/**
* Get all the proofs matching the capabilities. Proofs are delegations with
* an audience matching the agent DID.
Expand All @@ -155,6 +163,10 @@ export interface KeyringContextActions {
* Import a proof that delegates `*` ability on a space to this agent
*/
addSpace: (proof: Delegation) => Promise<void>
/**
* Get the plan
*/
getPlan: (email: Email) => Promise<PlanGetResult>
}

export type CreateDelegationOptions = Omit<UCANOptions, 'audience'> & {
Expand Down Expand Up @@ -191,6 +203,13 @@ export function getSpaces (agent: Agent): Space[] {
return spaces
}

/**
* Get plan of the account identified by the given email.
*/
export async function getPlan (agent: Agent, email: Email): Promise<Ucanto.Result<PlanGetSuccess, PlanGetFailure | Ucanto.Failure>> {
return await getAccountPlan(agent, DidMailto.fromEmail(email))
}

export interface CreateAgentOptions extends ServiceConfig {}

/**
Expand All @@ -200,20 +219,18 @@ export interface CreateAgentOptions extends ServiceConfig {}
export async function createAgent (
options: CreateAgentOptions = {}
): Promise<Agent> {
const dbName = `${DB_NAME}${
options.servicePrincipal != null ? '@' + options.servicePrincipal.did() : ''
}`
const dbName = `${DB_NAME}${options.servicePrincipal != null ? '@' + options.servicePrincipal.did() : ''}`
const store = new StoreIndexedDB(dbName, {
dbVersion: 1,
dbStoreName: DB_STORE_NAME
})
const raw = await store.load()
if (raw != null) {
return Object.assign(Agent.from(raw, { ...options, store }), { store })
return Object.assign(AccessAgent.from(raw, { ...options, store }), { store })
}
const principal = await RSASigner.generate()
return Object.assign(
await Agent.create({ principal }, { ...options, store }),
await AccessAgent.create({ principal }, { ...options, store }),
{ store }
)
}
2 changes: 1 addition & 1 deletion packages/keyring-core/test/agent.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { test, expect } from 'vitest'
import 'fake-indexeddb/auto'

import { createAgent } from '../src/index'
import { createAgent } from '../src/index.js'

test('createAgent', async () => {
const agent = await createAgent()
Expand Down
4 changes: 2 additions & 2 deletions packages/react-keyring/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
"devDependencies": {
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"@ucanto/interface": "^8.0.0",
"@ucanto/principal": "^8.0.0"
"@ucanto/interface": "^9.0.0",
"@ucanto/principal": "^9.0.0"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
Expand Down
3 changes: 2 additions & 1 deletion packages/react-keyring/src/Authenticator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ export const AuthenticatorContext = createContext<AuthenticatorContextValue>([
throw new Error('missing keyring context provider')
},
addSpace: async () => {},
authorize: async () => {}
authorize: async () => {},
getPlan: async () => ({ error: { name: 'KeyringContextMissing', message: 'missing keyring context provider' } })
}
])

Expand Down
20 changes: 15 additions & 5 deletions packages/react-keyring/src/providers/Keyring.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import type {
KeyringContextState,
KeyringContextActions,
ServiceConfig,
RegisterSpaceOpts
RegisterSpaceOpts,
Email,
Plan,
PlanGetResult
} from '@w3ui/keyring-core'
import type {
Capability,
Expand All @@ -23,11 +26,12 @@ import {
Space,
getCurrentSpace as getCurrentSpaceInAgent,
getSpaces,
getPlan as getPlanWithAgent,
CreateDelegationOptions,
W3UI_ACCOUNT_LOCALSTORAGE_KEY
} from '@w3ui/keyring-core'

export { KeyringContextState, KeyringContextActions }
export { Plan, KeyringContextState, KeyringContextActions }

export type KeyringContextValue = [
state: KeyringContextState,
Expand Down Expand Up @@ -56,7 +60,8 @@ export const keyringContextDefaultValue: KeyringContextValue = [
createDelegation: async () => {
throw new Error('missing keyring context provider')
},
addSpace: async () => {}
addSpace: async () => {},
getPlan: async () => ({ error: { name: 'KeyringContextMissing', message: 'missing keyring context provider' } })
}
]

Expand Down Expand Up @@ -161,7 +166,6 @@ export function KeyringProvider ({

const resetAgent = async (): Promise<void> => {
const agent = await getAgent()
// @ts-expect-error TODO expose store from access client
await Promise.all([agent.store.reset(), unloadAgent()])
}

Expand Down Expand Up @@ -193,6 +197,11 @@ export function KeyringProvider ({
await agent.importSpaceFromDelegation(proof)
}

const getPlan = async (email: Email): Promise<PlanGetResult> => {
const agent = await getAgent()
return await getPlanWithAgent(agent, email)
}

const state = {
space,
spaces,
Expand All @@ -210,7 +219,8 @@ export function KeyringProvider ({
setCurrentSpace,
getProofs,
createDelegation,
addSpace
addSpace,
getPlan
}

return (
Expand Down
2 changes: 1 addition & 1 deletion packages/react-uploader/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"dependencies": {
"@w3ui/react-keyring": "workspace:^6.0.1",
"@w3ui/uploader-core": "workspace:^",
"@web3-storage/capabilities": "^7.0.0",
"@web3-storage/capabilities": "^11.1.0",
"ariakit-react-utils": "0.17.0-next.27"
},
"peerDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/react-uploads-list/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"dependencies": {
"@w3ui/react-keyring": "workspace:^6.0.1",
"@w3ui/uploads-list-core": "workspace:^",
"@web3-storage/capabilities": "^7.0.0",
"@web3-storage/capabilities": "^11.1.0",
"ariakit-react-utils": "0.17.0-next.27"
},
"peerDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions packages/solid-keyring/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
},
"homepage": "https://github.com/web3-storage/w3ui/tree/main/packages/solid-keyring",
"dependencies": {
"@ucanto/interface": "^8.0.0",
"@ucanto/principal": "^8.0.0",
"@ucanto/interface": "^9.0.0",
"@ucanto/principal": "^9.0.0",
"@w3ui/keyring-core": "workspace:^5.0.1"
},
"peerDependencies": {
Expand Down
17 changes: 13 additions & 4 deletions packages/solid-keyring/src/providers/Keyring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import type {
ServiceConfig,
CreateDelegationOptions,
Agent,
Abilities
Abilities,
Email,
PlanGetResult
} from '@w3ui/keyring-core'
import type { Delegation, Capability, DID, Principal } from '@ucanto/interface'

Expand All @@ -21,6 +23,7 @@ import {
createAgent,
getCurrentSpace as getCurrentSpaceInAgent,
getSpaces,
getPlan as getPlanWithAgent,
W3UI_ACCOUNT_LOCALSTORAGE_KEY
} from '@w3ui/keyring-core'

Expand Down Expand Up @@ -55,7 +58,8 @@ export const AuthContext: Context<KeyringContextValue> = createContext<KeyringCo
throw new Error('missing keyring context provider')
},
addSpace: async () => {},
authorize: async () => {}
authorize: async () => {},
getPlan: async () => ({ error: { name: 'KeyringContextMissing', message: 'missing keyring context provider' } })
}
])

Expand Down Expand Up @@ -158,7 +162,6 @@ export const KeyringProvider: ParentComponent<KeyringProviderProps> = (

const resetAgent = async (): Promise<void> => {
const agent = await getAgent()
// @ts-expect-error TODO: expose store in access client
await Promise.all([agent.store.reset(), unloadAgent()])
}

Expand All @@ -167,6 +170,11 @@ export const KeyringProvider: ParentComponent<KeyringProviderProps> = (
return agent.proofs(caps)
}

const getPlan = async (email: Email): Promise<PlanGetResult> => {
const agent = await getAgent()
return await getPlanWithAgent(agent, email)
}

const createDelegation = async (
audience: Principal,
abilities: Abilities[],
Expand Down Expand Up @@ -201,7 +209,8 @@ export const KeyringProvider: ParentComponent<KeyringProviderProps> = (
createDelegation,
addSpace,
authorize,
cancelAuthorize
cancelAuthorize,
getPlan
}

return createComponent(AuthContext.Provider, {
Expand Down
2 changes: 1 addition & 1 deletion packages/solid-uploader/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"dependencies": {
"@w3ui/solid-keyring": "workspace:^5.0.1",
"@w3ui/uploader-core": "workspace:^",
"@web3-storage/capabilities": "^7.0.0",
"@web3-storage/capabilities": "^11.1.0",
"multiformats": "^11.0.1"
},
"peerDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions packages/solid-uploads-list/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@
"dependencies": {
"@w3ui/solid-keyring": "workspace:^5.0.1",
"@w3ui/uploads-list-core": "workspace:^",
"@web3-storage/capabilities": "^7.0.0"
"@web3-storage/capabilities": "^11.1.0"
},
"peerDependencies": {
"solid-js": "^1.7.8"
},
"devDependencies": {
"@ucanto/interface": "^8.0.0"
"@ucanto/interface": "^9.0.0"
},
"eslintConfig": {
"extends": [
Expand Down
4 changes: 2 additions & 2 deletions packages/uploader-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
},
"homepage": "https://github.com/web3-storage/w3ui/tree/main/packages/uploader-core",
"dependencies": {
"@ucanto/interface": "^8.0.0",
"@web3-storage/upload-client": "^9.1.0",
"@ucanto/interface": "^9.0.0",
"@web3-storage/upload-client": "^11.1.0",
"multiformats": "^11.0.1"
},
"eslintConfig": {
Expand Down
4 changes: 2 additions & 2 deletions packages/uploads-list-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
},
"homepage": "https://github.com/web3-storage/w3ui/tree/main/packages/uploads-list-core",
"dependencies": {
"@ucanto/interface": "^8.0.0",
"@web3-storage/upload-client": "^9.1.0"
"@ucanto/interface": "^9.0.0",
"@web3-storage/upload-client": "^11.1.0"
},
"eslintConfig": {
"extends": [
Expand Down
4 changes: 2 additions & 2 deletions packages/vue-keyring/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
"vue": "^3.0.0"
},
"devDependencies": {
"@ucanto/interface": "^8.0.0",
"@ucanto/principal": "^8.0.0"
"@ucanto/interface": "^9.0.0",
"@ucanto/principal": "^9.0.0"
},
"eslintConfig": {
"extends": [
Expand Down
Loading