Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(backend): track if receiver is local #2862

Merged
merged 5 commits into from
Aug 21, 2024
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
6 changes: 4 additions & 2 deletions packages/backend/src/graphql/resolvers/receiver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ describe('Receiver Resolver', (): void => {
incomingAmount: incomingAmount
? serializeAmount(incomingAmount)
: undefined
})
}),
false
)

const createSpy = jest
Expand Down Expand Up @@ -253,7 +254,8 @@ describe('Receiver Resolver', (): void => {
id: `${walletAddress.id}/incoming-payments/${uuid()}`,
walletAddress: walletAddress.id,
incomingAmount: amount ? serializeAmount(amount) : undefined
})
}),
false
)

test('returns receiver', async (): Promise<void> => {
Expand Down
13 changes: 8 additions & 5 deletions packages/backend/src/open_payments/receiver/model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ describe('Receiver Model', (): void => {
const incomingPayment = await createIncomingPayment(deps, {
walletAddressId: walletAddress.id
})
const isLocal = true

const streamCredentials = streamCredentialsService.get(incomingPayment)
assert(streamCredentials)
Expand All @@ -50,7 +51,8 @@ describe('Receiver Model', (): void => {
incomingPayment.toOpenPaymentsTypeWithMethods(
walletAddress,
streamCredentials
)
),
isLocal
)

expect(receiver).toEqual({
Expand All @@ -74,7 +76,8 @@ describe('Receiver Model', (): void => {
sharedSecret: base64url(streamCredentials.sharedSecret)
}
]
}
},
isLocal
})
})

Expand All @@ -96,7 +99,7 @@ describe('Receiver Model', (): void => {
streamCredentials
)

expect(() => new Receiver(openPaymentsIncomingPayment)).toThrow(
expect(() => new Receiver(openPaymentsIncomingPayment, false)).toThrow(
'Cannot create receiver from completed incoming payment'
)
})
Expand All @@ -116,7 +119,7 @@ describe('Receiver Model', (): void => {
streamCredentials
)

expect(() => new Receiver(openPaymentsIncomingPayment)).toThrow(
expect(() => new Receiver(openPaymentsIncomingPayment, false)).toThrow(
'Cannot create receiver from expired incoming payment'
)
})
Expand All @@ -137,7 +140,7 @@ describe('Receiver Model', (): void => {
streamCredentials
)

expect(() => new Receiver(openPaymentsIncomingPayment)).toThrow(
expect(() => new Receiver(openPaymentsIncomingPayment, false)).toThrow(
'Invalid ILP address on ilp payment method'
)
})
Expand Down
7 changes: 6 additions & 1 deletion packages/backend/src/open_payments/receiver/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ export class Receiver {
public readonly assetCode: string
public readonly assetScale: number
public readonly incomingPayment: ReceiverIncomingPayment
public readonly isLocal: boolean

constructor(incomingPayment: OpenPaymentsIncomingPaymentWithPaymentMethod) {
constructor(
incomingPayment: OpenPaymentsIncomingPaymentWithPaymentMethod,
isLocal: boolean
) {
if (incomingPayment.completed) {
throw new Error('Cannot create receiver from completed incoming payment')
}
Expand Down Expand Up @@ -76,6 +80,7 @@ export class Receiver {
createdAt: new Date(incomingPayment.createdAt),
updatedAt: new Date(incomingPayment.updatedAt)
}
this.isLocal = isLocal
}

public get asset(): AssetOptions {
Expand Down
12 changes: 8 additions & 4 deletions packages/backend/src/open_payments/receiver/service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ describe('Receiver Service', (): void => {
sharedSecret: expect.any(String)
}
]
}
},
isLocal: true
})
})

Expand Down Expand Up @@ -260,7 +261,8 @@ describe('Receiver Service', (): void => {
sharedSecret: expect.any(String)
}
]
}
},
isLocal: false
})
if (!existingGrant) {
expect(clientRequestGrantSpy).toHaveBeenCalledWith(
Expand Down Expand Up @@ -480,7 +482,8 @@ describe('Receiver Service', (): void => {
sharedSecret: expect.any(String)
}
]
}
},
isLocal: false
})

expect(remoteIncomingPaymentServiceSpy).toHaveBeenCalledWith({
Expand Down Expand Up @@ -573,7 +576,8 @@ describe('Receiver Service', (): void => {
sharedSecret: expect.any(String)
}
]
}
},
isLocal: true
})

expect(incomingPaymentCreateSpy).toHaveBeenCalledWith({
Expand Down
74 changes: 38 additions & 36 deletions packages/backend/src/open_payments/receiver/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ async function createReceiver(
const localWalletAddress = await deps.walletAddressService.getByUrl(
args.walletAddressUrl
)
const isLocal = !!localWalletAddress

const incomingPaymentOrError = localWalletAddress
const incomingPaymentOrError = isLocal
? await createLocalIncomingPayment(deps, args, localWalletAddress)
: await deps.remoteIncomingPaymentService.create(args)

Expand All @@ -84,7 +85,7 @@ async function createReceiver(
}

try {
return new Receiver(incomingPaymentOrError)
return new Receiver(incomingPaymentOrError, isLocal)
} catch (error) {
const errorMessage = 'Could not create receiver from incoming payment'
deps.logger.error(
Expand Down Expand Up @@ -147,10 +148,27 @@ async function getReceiver(
deps: ServiceDependencies,
url: string
): Promise<Receiver | undefined> {
const incomingPayment = await getIncomingPayment(deps, url)
if (incomingPayment) {
return new Receiver(incomingPayment)
try {
const localIncomingPayment = await getLocalIncomingPayment({
deps,
url
})
if (localIncomingPayment) {
return new Receiver(localIncomingPayment, true)
}

const remoteIncomingPayment = await getRemoteIncomingPayment(deps, url)
if (remoteIncomingPayment) {
return new Receiver(remoteIncomingPayment, false)
}
} catch (error) {
deps.logger.error(
{ errorMessage: error instanceof Error && error.message },
'Could not get incoming payment'
)
}

return undefined
Comment on lines +151 to +171
Copy link
Contributor Author

@BlairCurrey BlairCurrey Aug 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The real change here in getReceiver is that we create the receiver with isLocal. The other changes in the receiverService.get are a little refactor in support of this. Just moves the attempt to get the local incoming payment into this main getReceiver function so I dont have to return more stuff from getIncomingPayment (now getRemoteIncomingPayment, since thats all it does).

}

function parseIncomingPaymentUrl(
Expand All @@ -167,49 +185,33 @@ function parseIncomingPaymentUrl(
}
}

async function getIncomingPayment(
async function getRemoteIncomingPayment(
deps: ServiceDependencies,
url: string
): Promise<OpenPaymentsIncomingPaymentWithPaymentMethods | undefined> {
try {
const urlParseResult = parseIncomingPaymentUrl(url)
if (!urlParseResult) {
return undefined
}

const localIncomingPayment = await getLocalIncomingPayment({
deps,
id: urlParseResult.id
const grant = await getIncomingPaymentGrant(deps, url)
if (!grant) {
throw new Error('Could not find grant')
} else {
return await deps.openPaymentsClient.incomingPayment.get({
url,
accessToken: grant.accessToken
})
if (localIncomingPayment) {
return localIncomingPayment
}

const grant = await getIncomingPaymentGrant(deps, url)
if (!grant) {
throw new Error('Could not find grant')
} else {
return await deps.openPaymentsClient.incomingPayment.get({
url,
accessToken: grant.accessToken
})
}
} catch (error) {
deps.logger.error(
{ errorMessage: error instanceof Error && error.message },
'Could not get incoming payment'
)
return undefined
}
}

async function getLocalIncomingPayment({
deps,
id
url
}: {
deps: ServiceDependencies
id: string
url: string
}): Promise<OpenPaymentsIncomingPaymentWithPaymentMethods | undefined> {
const { id } = parseIncomingPaymentUrl(url) ?? {}
if (!id) {
return undefined
}

const incomingPayment = await deps.incomingPaymentService.get({
id
})
Expand Down
6 changes: 4 additions & 2 deletions packages/backend/src/tests/outgoingPayment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ export async function createOutgoingPayment(
incomingPayment.toOpenPaymentsTypeWithMethods(
walletAddress,
streamCredentials
)
),
false
)
)
}
Expand Down Expand Up @@ -124,7 +125,8 @@ export async function createOutgoingPaymentWithReceiver(
incomingPayment.toOpenPaymentsTypeWithMethods(
args.receivingWalletAddress,
streamCredentials
)
),
false
)

const outgoingPayment = await createOutgoingPayment(deps, {
Expand Down
3 changes: 2 additions & 1 deletion packages/backend/src/tests/receiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export async function createReceiver(
incomingPayment.toOpenPaymentsTypeWithMethods(
walletAddress,
streamCredentialsService.get(incomingPayment)!
)
),
false
)
}
Loading