Skip to content

Commit

Permalink
feat(rdt): add subintent request builder
Browse files Browse the repository at this point in the history
  • Loading branch information
xstelea committed Oct 17, 2024
1 parent 4ccd67c commit b316c02
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 29 deletions.
16 changes: 7 additions & 9 deletions examples/simple-dapp/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
OneTimeDataRequestBuilder,
LocalStorageModule,
generateRolaChallenge,
SubintentRequestBuilder,
} from '@radixdlt/radix-dapp-toolkit'

const dAppDefinitionAddress = import.meta.env.VITE_DAPP_DEFINITION_ADDRESS
Expand Down Expand Up @@ -85,16 +86,13 @@ removeCb.onclick = () => {

subintentButton.onclick = async () => {
console.log(subintentManifest.value)
const result = await dAppToolkit.walletApi.sendPreAuthorizationRequest({
transactionManifest: subintentManifest.value,
childSubintentHashes: [],
expiration: {
discriminator: 'expireAfterSignature',
value: 3600,
},
})
const result = await dAppToolkit.walletApi.sendPreAuthorizationRequest(
SubintentRequestBuilder()
.manifest(subintentManifest.value)
.setExpiration('secondsAfterSignature', 3600),
)

console.log(result);
console.log(result)
}

addCb.onclick = () => {
Expand Down
10 changes: 2 additions & 8 deletions packages/dapp-toolkit/src/_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type {
WalletRequestModule,
ConnectButtonModule,
} from './modules'
import { BuildableSubintentRequest } from './modules/wallet-request/pre-authorization-request/subintent-builder'

export type Providers = {
connectButtonModule: ConnectButtonModule
Expand Down Expand Up @@ -100,14 +101,7 @@ export type SendTransactionInput = {
onTransactionId?: (transactionId: string) => void
}

export type SendPreAuthorizationRequestInput = {
transactionManifest: string
version?: number
blobs?: string[]
message?: string
childSubintentHashes: string[]
expiration: ExpireAtTime | ExpireAfterSignature
}
export type SendPreAuthorizationRequestInput = BuildableSubintentRequest

export type ButtonApi = {
setMode: (value: 'light' | 'dark') => void
Expand Down
1 change: 1 addition & 0 deletions packages/dapp-toolkit/src/modules/wallet-request/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './session/session.module'
export * from './transport'
export * from './wallet-request-sdk'
export * from './wallet-request'
export * from './pre-authorization-request'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './subintent-builder'
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { describe, expect, it } from 'vitest'
import { SubintentRequestBuilder } from './subintent-builder'

describe('SubintentRequestBuilder', () => {
it('should build a subintent request', () => {
const tx = SubintentRequestBuilder()
.manifest('...')
.setExpiration('secondsAfterSignature', 60)
.addBlobs('deadbeef', 'beefdead')
.message('hello')
.toRequestItem()

expect(tx).toEqual({
discriminator: 'subintent',
version: 1,
transactionManifestVersion: 1,
transactionManifest: '...',
expiration: {
discriminator: 'expireAfterSignature',
value: 60,
},
blobs: ['deadbeef', 'beefdead'],
message: 'hello',
})
})

it('should build a subintent request using raw object', () => {
const tx = SubintentRequestBuilder()
.rawConfig({
version: 1,
transactionManifestVersion: 1,
transactionManifest: '...',
expiration: {
discriminator: 'expireAfterSignature',
value: 60,
},
blobs: ['deadbeef', 'beefdead'],
message: 'hello',
})
.toRequestItem()

expect(tx).toEqual({
discriminator: 'subintent',
version: 1,
transactionManifestVersion: 1,
transactionManifest: '...',
expiration: {
discriminator: 'expireAfterSignature',
value: 60,
},
blobs: ['deadbeef', 'beefdead'],
message: 'hello',
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { SubintentRequestItem } from '../../../schemas'

export type BuildableSubintentRequest = {
toRequestItem: () => SubintentRequestItem
}
/**
* A builder function for creating a SubintentRequest.
*
* @returns An object with methods to configure and build a SubintentRequestItem.
*
* @example
* const builder = SubintentRequestBuilder();
* const requestItem = builder
* .manifest('some-manifest')
* .setExpiration('atTime', 1234567890)
* .addBlobs('blob1', 'blob2')
* .message('This is a message')
*
* @method setExpiration
* Sets the expiration for the subintent request.
*
* @param type - The type of expiration, either 'atTime' or 'secondsAfterSignature'.
* @param value - The value of the expiration. If type is 'atTime', this is a Unix timestamp. If type is 'secondsAfterSignature', this is the number of seconds after the signature is created.
* @returns The API object for chaining.
*
* @method addBlobs
* Adds blobs to the subintent request.
*
* @param values - The blobs to add.
* @returns The API object for chaining.
*
* @method message
* Sets a message for the subintent request.
*
* @param value - The message to set.
* @returns The API object for chaining.
*
* @method manifest
* Sets the transaction manifest for the subintent request.
*
* @param value - The transaction manifest to set.
* @returns The API object for chaining.
*
* @method toRequestItem
* Converts the current state to a SubintentRequestItem.
*
* @returns The SubintentRequestItem.
*
* @method rawConfig
* Sets the raw configuration for the subintent request.
*
* @param rawConfig - The raw configuration object, excluding the discriminator.
* @returns An object with the toRequestItem method.
*/
export const SubintentRequestBuilder = () => {
let state: Partial<SubintentRequestItem> = {
discriminator: 'subintent',
version: 1,
transactionManifestVersion: 1,
}

const setExpiration = (
type: 'atTime' | 'secondsAfterSignature',
value: number,
) => {
state.expiration = {
discriminator:
type === 'atTime' ? 'expireAtTime' : 'expireAfterSignature',
value,
}
return api
}

const addBlobs = (...values: string[]) => {
state.blobs = values
return api
}

const message = (value: string) => {
state.message = value
return api
}

const manifest = (value: string) => {
state.transactionManifest = value
return api
}

const toRequestItem = () => state as SubintentRequestItem

const rawConfig = (
rawConfig: Omit<SubintentRequestItem, 'discriminator'>,
) => {
state = { ...rawConfig, discriminator: 'subintent' }
return { toRequestItem }
}

const api = {
setExpiration,
addBlobs,
message,
toRequestItem,
} as const

return { manifest, rawConfig }
}
13 changes: 2 additions & 11 deletions packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ import {
import { validateRolaChallenge, type Logger } from '../../helpers'
import { TransactionStatus } from '../gateway'
import { ResultAsync, err, ok, okAsync } from 'neverthrow'
import type {
MessageLifeCycleEvent,
WalletInteraction,
} from '../../schemas'
import type { MessageLifeCycleEvent, WalletInteraction } from '../../schemas'
import { SdkError } from '../../error'
import {
DataRequestBuilderItem,
Expand Down Expand Up @@ -310,13 +307,7 @@ export const WalletRequestModule = (input: {
> => {
const walletInteraction = walletRequestSdk.createWalletInteraction({
discriminator: 'preAuthorizationRequest',
subintent: {
discriminator: 'subintent',
blobs: value.blobs,
transactionManifest: value.transactionManifest,
message: value.message,
version: value.version ?? 1,
},
subintent: value.toRequestItem(),
})

return addNewRequest('preAuthorizationRequest', walletInteraction, false)
Expand Down
2 changes: 1 addition & 1 deletion packages/dapp-toolkit/src/schemas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,10 @@ export type SubintentRequestItem = InferOutput<typeof SubintentRequestItem>
export const SubintentRequestItem = object({
discriminator: literal('subintent'),
version: number(),
transactionManifestVersion: number(),
transactionManifest: string(),
blobs: optional(array(string())),
message: optional(string()),
childSubintentHashes: optional(array(string())),
expiration: optional(union([ExpireAtTime, ExpireAfterSignature])),
})

Expand Down

0 comments on commit b316c02

Please sign in to comment.