Skip to content
Open
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
2 changes: 1 addition & 1 deletion examples/cli/src/commands/datasets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const datasets: Command = command(
spinner.stop('Data sets:')
dataSets.forEach(async (dataSet) => {
p.log.info(
`#${dataSet.dataSetId} ${dataSet.cdn ? 'CDN' : ''} ${dataSet.provider.pdp.serviceURL} ${dataSet.pdpEndEpoch > 0n ? `Terminating at epoch ${dataSet.pdpEndEpoch}` : ''} ${dataSet.live ? 'Live' : ''} ${dataSet.managed ? 'Managed' : ''}`
`#${dataSet.dataSetId} ${dataSet.provider.payee} ${dataSet.cdn ? 'CDN' : ''} ${dataSet.provider.pdp.serviceURL} ${dataSet.pdpEndEpoch > 0n ? `Terminating at epoch ${dataSet.pdpEndEpoch}` : ''} ${dataSet.live ? 'Live' : ''} ${dataSet.managed ? 'Managed' : ''}`
)
})
p.log.warn(`Block number: ${blockNumber}`)
Expand Down
90 changes: 90 additions & 0 deletions examples/cli/src/commands/session-keys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import * as p from '@clack/prompts'
import * as SessionKey from '@filoz/synapse-core/session-key'
import { createDataSet, waitForCreateDataSet } from '@filoz/synapse-core/sp'
import { type Command, command } from 'cleye'
import type { Hex } from 'viem'
import { privateKeyClient } from '../client.ts'
import { globalFlags } from '../flags.ts'
import { hashLink } from '../utils.ts'

export const sessionKeys: Command = command(
{
name: 'session-keys',
description: 'Manage session keys',
alias: 'sk',
flags: {
...globalFlags,
},
help: {
description: 'Manage session keys',
},
},
async (argv) => {
const { client, chain } = privateKeyClient(argv.flags.chain)

console.log('🚀 ~ client.account.address:', client.account.address)

const sessionKey = SessionKey.fromSecp256k1({
privateKey:
'0xaa14e25eaea762df1533e72394b85e56dd0c7aa61cf6df3b1f13a842ca0361e5' as Hex,
root: client.account,
chain,
})

sessionKey.on('expirationsUpdated', (e) => {
console.log('🚀 ~ expirations:', e.detail)
})
sessionKey.on('connected', (e) => {
console.log('🚀 ~ connected:', e.detail)
})
sessionKey.on('disconnected', () => {
console.log('🚀 ~ disconnected')
})
sessionKey.on('error', (e) => {
console.log('🚀 ~ error:', e.detail)
})

const { event: loginEvent } = await SessionKey.loginSync(client, {
address: sessionKey.address,
onHash(hash) {
p.log.info(`Waiting for tx ${hashLink(hash, chain)} to be mined...`)
},
})
console.log('🚀 ~ event:', loginEvent.args)

await sessionKey.connect()

if (sessionKey.hasPermission(SessionKey.CreateDataSetPermission)) {
const result = await createDataSet(sessionKey.client, {
payee: '0xa3971A7234a3379A1813d9867B531e7EeB20ae07',
payer: sessionKey.rootAddress,
serviceURL: 'https://calib.ezpdpz.net',
cdn: false,
})
p.log.info(
`Waiting for tx ${hashLink(result.txHash, chain)} to be mined...`
)
const dataset = await waitForCreateDataSet(result)
p.log.info(`Data set created #${dataset.dataSetId}`)
} else {
p.log.error('Session key does not have permission to create data set')
}

// const { event: revokeEvent } = await SessionKey.revokeSync(client, {
// address: sessionKey.address,
// onHash(hash) {
// p.log.info(`Waiting for tx ${hashLink(hash, chain)} to be mined...`)
// },
// })
// console.log('🚀 ~ event revoked:', revokeEvent.args)
sessionKey.disconnect()
// try {
// } catch (error) {
// if (argv.flags.debug) {
// console.error(error)
// } else {
// p.log.error((error as Error).message)
// }
// }
}
)
2 changes: 2 additions & 0 deletions examples/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { pay } from './commands/pay.ts'
import { pieces } from './commands/pieces.ts'
import { piecesRemoval } from './commands/pieces-removal.ts'
import { piecesUpload } from './commands/pieces-upload.ts'
import { sessionKeys } from './commands/session-keys.ts'
import { upload } from './commands/upload.ts'
import { uploadDataset } from './commands/upload-dataset.ts'
import { withdraw } from './commands/withdraw.ts'
Expand All @@ -37,6 +38,7 @@ const argv = cli({
piecesUpload,
uploadDataset,
getSpPeerIds,
sessionKeys,
],
})

Expand Down
108 changes: 0 additions & 108 deletions packages/synapse-core/src/session-key/actions.ts

This file was deleted.

120 changes: 104 additions & 16 deletions packages/synapse-core/src/session-key/authorization-expiry.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import type { Simplify } from 'type-fest'
import type {
Address,
Chain,
Client,
ContractFunctionParameters,
ContractFunctionReturnType,
ReadContractErrorType,
Transport,
import {
type Address,
type Chain,
type Client,
ContractFunctionExecutionError,
type ContractFunctionParameters,
type ContractFunctionReturnType,
type MulticallErrorType,
type ReadContractErrorType,
type Transport,
} from 'viem'
import { readContract } from 'viem/actions'
import { multicall, readContract } from 'viem/actions'
import type { sessionKeyRegistry as sessionKeyRegistryAbi } from '../abis/index.ts'
import { asChain } from '../chains.ts'
import type { ActionCallChain } from '../types.ts'
import { SESSION_KEY_PERMISSIONS, type SessionKeyPermissions } from './permissions.ts'
import { DefaultFwssPermissions, type Expirations, type Permission } from './permissions.ts'

export namespace authorizationExpiry {
export type OptionsType = {
Expand All @@ -21,7 +23,7 @@ export namespace authorizationExpiry {
/** The address of the session key. */
sessionKeyAddress: Address
/** The session key permission. */
permission: SessionKeyPermissions
permission: Permission
/** Session key registry contract address. If not provided, the default is the session key registry contract address for the chain. */
contractAddress?: Address
}
Expand Down Expand Up @@ -51,7 +53,7 @@ export namespace authorizationExpiry {
*
* @example
* ```ts
* import { authorizationExpiry } from '@filoz/synapse-core/session-key'
* import { authorizationExpiry, CreateDataSetPermission } from '@filoz/synapse-core/session-key'
* import { createPublicClient, http } from 'viem'
* import { calibration } from '@filoz/synapse-core/chains'
*
Expand All @@ -63,7 +65,7 @@ export namespace authorizationExpiry {
* const expiry = await authorizationExpiry(client, {
* address: '0x1234567890123456789012345678901234567890',
* sessionKeyAddress: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd',
* permission: 'CreateDataSet',
* permission: CreateDataSetPermission,
* })
*
* console.log('Authorization expires at:', expiry)
Expand Down Expand Up @@ -107,7 +109,7 @@ export namespace authorizationExpiryCall {
*
* @example
* ```ts
* import { authorizationExpiryCall } from '@filoz/synapse-core/session-key'
* import { authorizationExpiryCall, CreateDataSetPermission } from '@filoz/synapse-core/session-key'
* import { createPublicClient, http } from 'viem'
* import { multicall } from 'viem/actions'
* import { calibration } from '@filoz/synapse-core/chains'
Expand All @@ -123,7 +125,7 @@ export namespace authorizationExpiryCall {
* chain: calibration,
* address: '0x1234567890123456789012345678901234567890',
* sessionKeyAddress: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd',
* permission: 'CreateDataSet',
* permission: CreateDataSetPermission,
* }),
* ],
* })
Expand All @@ -137,6 +139,92 @@ export function authorizationExpiryCall(options: authorizationExpiryCall.Options
abi: chain.contracts.sessionKeyRegistry.abi,
address: options.contractAddress ?? chain.contracts.sessionKeyRegistry.address,
functionName: 'authorizationExpiry',
args: [options.address, options.sessionKeyAddress, SESSION_KEY_PERMISSIONS[options.permission]],
args: [options.address, options.sessionKeyAddress, options.permission],
} satisfies authorizationExpiryCall.OutputType
}

export namespace isExpired {
export type OptionsType = Simplify<authorizationExpiry.OptionsType>
export type ErrorType = authorizationExpiry.ErrorType
export type OutputType = boolean
}

/**
* Check if the session key is expired.
*
* @param client - The client to use.
* @param options - The options to use.
* @returns Whether the session key is expired.
* @throws - {@link isExpired.ErrorType} if the read contract fails.
*/
export async function isExpired(
client: Client<Transport, Chain>,
options: isExpired.OptionsType
): Promise<isExpired.OutputType> {
const expiry = await authorizationExpiry(client, options)

return expiry < BigInt(Math.floor(Date.now() / 1000))
}

export namespace getExpirations {
export type OptionsType = Simplify<
Omit<authorizationExpiry.OptionsType, 'permission'> & { permissions?: Permission[] }
>
export type ErrorType = authorizationExpiry.ErrorType | MulticallErrorType
export type OutputType = Record<Permission, bigint>
}

/**
* Get the expirations for all FWSS permissions.
*
* @param client - The client to use.
* @param options - {@link getExpirations.OptionsType}
* @returns Expirations {@link getExpirations.OutputType}
* @throws Errors {@link getExpirations.ErrorType}
*
* @example
* ```ts
* import { getExpirations } from '@filoz/synapse-core/session-key'
* import { createPublicClient, http } from 'viem'
* import { calibration } from '@filoz/synapse-core/chains'
*
* const client = createPublicClient({
* chain: calibration,
* transport: http(),
* })
*
* const expirations = await getExpirations(client, {
* address: '0x1234567890123456789012345678901234567890',
* sessionKeyAddress: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd',
* })
*
* console.log(expirations)
*/
export async function getExpirations(client: Client<Transport, Chain>, options: getExpirations.OptionsType) {
const permissions = options.permissions ?? DefaultFwssPermissions
const expirations: Expirations = Object.fromEntries(permissions.map((permission) => [permission, 0n]))

try {
const result = await multicall(client, {
allowFailure: false,
contracts: permissions.map((permission) =>
authorizationExpiryCall({
chain: client.chain,
address: options.address,
sessionKeyAddress: options.sessionKeyAddress,
permission,
})
),
})

for (let i = 0; i < permissions.length; i++) {
expirations[permissions[i]] = result[i]
}
} catch (e) {
if (!(e instanceof ContractFunctionExecutionError && e.details.includes('actor not found'))) {
throw e
}
}

return expirations
}
Loading