-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
wip on sdk, fixing package publishing
- Loading branch information
Showing
14 changed files
with
909 additions
and
17 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,6 @@ | ||
export { buildRequest } from './lib/builders/request-builder' | ||
export * from './lib/engine-request' | ||
import EvaluationRequestBuilder from './lib/builders/evaluation-request' | ||
|
||
export { buildRequest } from './lib/builders/request/request-builder' | ||
export { ClientConfig, Endpoints, NarvalSdkConfig, PolicyEngineConfig } from './lib/domain' | ||
export { NarvalSdk } from './lib/narval-sdk' | ||
export { EvaluationRequestBuilder } |
61 changes: 51 additions & 10 deletions
61
packages/engine-request/src/lib/builders/evaluation-request.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,63 @@ | ||
import { Feed, JwtString, Prices } from '@narval/policy-engine-shared' | ||
import { EvaluationRequest, Feed, JwtString, Prices, Request } from '@narval/policy-engine-shared' | ||
import { Jwk, Payload, SignConfig, hash, signJwt } from '@narval/signature' | ||
import axios from 'axios' | ||
import { Endpoints, NarvalSdkConfig } from '../domain' | ||
|
||
export type EvaluationRequestConfig = { | ||
approvals?: JwtString[] | ||
prices?: Prices | ||
feeds?: Feed<unknown>[] | ||
} | ||
|
||
const buildPayloadFromRequest = (request: Request, jwk: Jwk, orgId: string): Payload => { | ||
return { | ||
requestHash: hash(request), | ||
sub: jwk.kid, | ||
iss: orgId, | ||
iat: new Date().getTime() | ||
} | ||
} | ||
|
||
export default class EvaluationRequestBuilder { | ||
private approvals?: JwtString[] | ||
private prices?: Prices | ||
private feeds?: Feed<unknown>[] | ||
|
||
setApprovals(approvals: JwtString[]) { | ||
this.approvals = approvals | ||
return this | ||
constructor(config?: EvaluationRequestConfig) { | ||
this.approvals = config?.approvals | ||
this.prices = config?.prices | ||
this.feeds = config?.feeds | ||
} | ||
|
||
setPrices(prices: Prices) { | ||
this.prices = prices | ||
return this | ||
async sign( | ||
request: Request, | ||
opts: { | ||
signConfig: SignConfig | ||
jwk: Jwk | ||
clientId: string | ||
} | ||
): Promise<EvaluationRequest> { | ||
const payload = buildPayloadFromRequest(request, opts.jwk, opts.clientId) | ||
const { signer, opts: signingOpts } = opts.signConfig | ||
const authentication = signer | ||
? await signJwt(payload, opts.jwk, signingOpts, signer) | ||
: await signJwt(payload, opts.jwk, signingOpts) | ||
return { | ||
authentication, | ||
request, | ||
approvals: this.approvals, | ||
prices: this.prices, | ||
feeds: this.feeds | ||
} | ||
} | ||
|
||
setFeeds(feeds: Feed<unknown>[]) { | ||
this.feeds = feeds | ||
return this | ||
async send(request: EvaluationRequest, config: NarvalSdkConfig): Promise<EvaluationRequest> { | ||
const response = await axios.post(`${config.engine.url}${Endpoints.engine.evaluations}`, request, { | ||
headers: { | ||
'x-client-id': config.client.id, | ||
'x-client-secret': config.client.secret | ||
} | ||
}) | ||
return response.data | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
packages/engine-request/src/lib/builders/request/organization-request.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { OrganizationAction } from '../../domain' | ||
|
||
export default class OrganizationBuilder { | ||
private action: OrganizationAction | null = null | ||
private nonce: string | ||
|
||
setAction(action: OrganizationAction) { | ||
this.action = action | ||
switch (action) { | ||
case OrganizationAction.CREATE_ORGANIZATION: | ||
return new CreateOrganizationBuilder() | ||
} | ||
} | ||
|
||
setNonce(nonce: string) { | ||
this.nonce = nonce | ||
return this | ||
} | ||
} | ||
|
||
class CreateOrganizationBuilder extends OrganizationBuilder { | ||
private organizationId: string | ||
|
||
setOrganization(organizationId: string) { | ||
this.organizationId = organizationId | ||
return this | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
packages/engine-request/src/lib/builders/request/request-builder.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { Category } from '../../domain' | ||
import OrganizationBuilder from './organization-request' | ||
import WalletRequestBuilder from './wallet-request' | ||
|
||
/** | ||
* Creates a request builder for either Wallet or Organization categories. | ||
* @param category - The category of the request to build. Either 'wallet' or 'organization'. | ||
* @returns A builder instance specific to the provided category, either WalletRequestBuilder or OrganizationBuilder. | ||
* @example | ||
* // For wallet-related requests | ||
* const walletBuilder = buildRequest('wallet'); | ||
* | ||
* // For organization-related requests | ||
* const organizationBuilder = buildRequest('organization'); | ||
*/ | ||
export function buildRequest(category: 'wallet'): WalletRequestBuilder | ||
export function buildRequest(category: 'organization'): OrganizationBuilder | ||
export function buildRequest(category: Category): OrganizationBuilder | WalletRequestBuilder { | ||
if (category === Category.WALLET) { | ||
return new WalletRequestBuilder() | ||
} else { | ||
return new OrganizationBuilder() | ||
} | ||
} |
220 changes: 220 additions & 0 deletions
220
packages/engine-request/src/lib/builders/request/wallet-request.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
import { | ||
Eip712TypedData, | ||
SignMessageAction, | ||
SignRawAction, | ||
SignTransactionAction, | ||
SignTypedDataAction, | ||
TransactionRequest | ||
} from '@narval/policy-engine-shared' | ||
import { v4 } from 'uuid' | ||
import { BuildResponse, WalletAction } from '../../domain' | ||
|
||
/** | ||
* Builder class for creating wallet-related requests, such as signing transactions, raw data, messages, or typed data. | ||
*/ | ||
export default class WalletRequestBuilder { | ||
private action: WalletAction | ||
private resourceId: string | ||
private nonce: string | ||
|
||
/** | ||
* Mandatory. Sets the action to be performed by the request. | ||
* @param action - The specific wallet action to perform. | ||
* @returns The builder instance specific to the action for method chaining. | ||
* @example | ||
* const request = buildRequest('wallet') | ||
* .setAction('signTransaction') | ||
* .setTransactionRequest(transactionRequest) | ||
* @example | ||
* const request = buildRequest('wallet') | ||
* .setAction('signRaw') | ||
* .setRawMessage(rawMessage) | ||
*/ | ||
setAction(action: 'signTransaction'): SignTransactionBuilder | ||
setAction(action: 'signRaw'): SignRawBuilder | ||
setAction(action: 'signMessage'): SignMessageBuilder | ||
setAction(action: 'signTypedData'): SignTypedDataBuilder | ||
setAction(action: WalletAction) { | ||
switch (action) { | ||
case WalletAction.SIGN_TRANSACTION: | ||
return new SignTransactionBuilder() | ||
case WalletAction.SIGN_RAW: | ||
return new SignRawBuilder() | ||
case WalletAction.SIGN_MESSAGE: | ||
return new SignMessageBuilder() | ||
case WalletAction.SIGN_TYPED_DATA: | ||
return new SignTypedDataBuilder() | ||
default: | ||
throw new Error(`Invalid action: ${action}`) | ||
} | ||
} | ||
|
||
/** | ||
* Optional. Sets the unique identifier for the transaction nonce. | ||
* @default v4() | ||
* @optional | ||
* @param nonce - The nonce value as a string. | ||
* @returns The builder instance for method chaining. | ||
*/ | ||
setNonce(nonce: string) { | ||
this.nonce = nonce | ||
return this | ||
} | ||
|
||
protected getNonce() { | ||
return this.nonce | ||
} | ||
|
||
protected getResourceId() { | ||
return this.resourceId | ||
} | ||
|
||
/** | ||
* Mandatory. Sets the resource identifier involved in the request, usually the wallet address. | ||
* @param resourceId - The Ethereum wallet address as a string. | ||
* @mandatory | ||
* @returns The builder instance for method chaining. | ||
*/ | ||
setResourceId(resourceId: string) { | ||
this.resourceId = resourceId | ||
return this | ||
} | ||
} | ||
|
||
class SignTransactionBuilder extends WalletRequestBuilder { | ||
private transactionRequest: TransactionRequest | ||
|
||
setTransactionRequest(transactionRequest: TransactionRequest) { | ||
this.transactionRequest = transactionRequest | ||
return this | ||
} | ||
|
||
/** | ||
* Constructs and returns the final request object based on the previously provided configurations. | ||
* @returns {BuildResponse<SignTransactionAction>} The final request object if all required configurations are valid, otherwise returns an error object. | ||
*/ | ||
build(): BuildResponse<SignTransactionAction> { | ||
const nonce = this.getNonce() || v4() | ||
const request = { | ||
action: WalletAction.SIGN_TRANSACTION, | ||
nonce, | ||
resourceId: this.getResourceId(), | ||
transactionRequest: this.transactionRequest | ||
} | ||
const res = SignTransactionAction.safeParse(request) | ||
return res.success | ||
? { | ||
success: true, | ||
request: res.data | ||
} | ||
: { | ||
success: false, | ||
error: res.error | ||
} | ||
} | ||
} | ||
|
||
class SignRawBuilder extends WalletRequestBuilder { | ||
private rawMessage: string | ||
private alg: string | ||
|
||
setRawMessage(rawMessage: string) { | ||
this.rawMessage = rawMessage | ||
return this | ||
} | ||
|
||
setAlg(alg: string) { | ||
this.alg = alg | ||
return this | ||
} | ||
|
||
/** | ||
* Constructs and returns the final request object based on the previously provided configurations. | ||
* @returns {BuildResponse<SignRawAction>} The final request object if all required configurations are valid, otherwise returns an error object. | ||
*/ | ||
build(): BuildResponse<SignRawAction> { | ||
const nonce = this.getNonce() || v4() | ||
const request = { | ||
action: WalletAction.SIGN_RAW, | ||
nonce, | ||
resourceId: this.getResourceId(), | ||
rawMessage: this.rawMessage | ||
} | ||
const res = SignRawAction.safeParse(request) | ||
return res.success | ||
? { | ||
success: true, | ||
request: res.data | ||
} | ||
: { | ||
success: false, | ||
error: res.error | ||
} | ||
} | ||
} | ||
|
||
class SignMessageBuilder extends WalletRequestBuilder { | ||
private message: string | ||
|
||
setMessage(message: string) { | ||
this.message = message | ||
return this | ||
} | ||
|
||
/** | ||
* Constructs and returns the final request object based on the previously provided configurations. | ||
* @returns {BuildResponse<SignMessageAction>} The final request object if all required configurations are valid, otherwise returns an error object. | ||
*/ | ||
build(): BuildResponse<SignMessageAction> { | ||
const nonce = this.getNonce() || v4() | ||
const request = { | ||
action: WalletAction.SIGN_MESSAGE, | ||
nonce, | ||
resourceId: this.getResourceId(), | ||
message: this.message | ||
} | ||
const res = SignMessageAction.safeParse(request) | ||
return res.success | ||
? { | ||
success: true, | ||
request: res.data | ||
} | ||
: { | ||
success: false, | ||
error: res.error | ||
} | ||
} | ||
} | ||
|
||
class SignTypedDataBuilder extends WalletRequestBuilder { | ||
private typedData: Eip712TypedData | ||
|
||
setTypedData(typedData: Eip712TypedData) { | ||
this.typedData = typedData | ||
return this | ||
} | ||
|
||
/** | ||
* Constructs and returns the final request object based on the previously provided configurations. | ||
* @returns {BuildResponse<SignTypedDataAction>} The final request object if all required configurations are valid, otherwise returns an error object. | ||
*/ | ||
build(): BuildResponse<SignTypedDataAction> { | ||
const nonce = this.getNonce() || v4() | ||
const request = { | ||
action: WalletAction.SIGN_TYPED_DATA, | ||
nonce, | ||
resourceId: this.getResourceId(), | ||
typedData: this.typedData | ||
} | ||
const res = SignTypedDataAction.safeParse(request) | ||
return res.success | ||
? { | ||
success: true, | ||
request: res.data | ||
} | ||
: { | ||
success: false, | ||
error: res.error | ||
} | ||
} | ||
} |
Oops, something went wrong.