Skip to content

LW-12881 Make KoraLabsHandleProvider compliant with bitcoin #1624

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

Merged
merged 1 commit into from
May 21, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,23 @@ export interface KoraLabsHandleProviderDeps {
policyId: Cardano.PolicyId;
}

export const toHandleResolution = ({
apiResponse,
policyId
}: {
apiResponse: IHandle;
policyId: Cardano.PolicyId;
}): HandleResolution => ({
backgroundImage: apiResponse.bg_image ? Asset.Uri(apiResponse.bg_image) : undefined,
cardanoAddress: Cardano.PaymentAddress(apiResponse.resolved_addresses.ada),
handle: apiResponse.name,
hasDatum: apiResponse.has_datum,
image: apiResponse.image ? Asset.Uri(apiResponse.image) : undefined,
policyId,
profilePic: apiResponse.pfp_image ? Asset.Uri(apiResponse.pfp_image) : undefined
});
export const toHandleResolution = ({ apiResponse, policyId }: { apiResponse: IHandle; policyId: Cardano.PolicyId }) => {
const cardano = Cardano.PaymentAddress(apiResponse.resolved_addresses.ada);
const result: HandleResolution = {
addresses: { cardano },
backgroundImage: apiResponse.bg_image ? Asset.Uri(apiResponse.bg_image) : undefined,
cardanoAddress: cardano,
handle: apiResponse.name,
hasDatum: apiResponse.has_datum,
image: apiResponse.image ? Asset.Uri(apiResponse.image) : undefined,
policyId,
profilePic: apiResponse.pfp_image ? Asset.Uri(apiResponse.pfp_image) : undefined
};

if ('btc' in apiResponse.resolved_addresses) result.addresses.bitcoin = apiResponse.resolved_addresses.btc;

return result;
};

/**
* Creates a KoraLabs Provider instance to resolve Standard Handles
Expand Down
15 changes: 10 additions & 5 deletions packages/cardano-services-client/test/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,25 @@ export const getWrongHandleProviderResponse = {
}
};

const aliceCardanoAddress =
'addr_test1qqk4sr4f7vtqzd2w90d5nfu3n59jhhpawyphnek2y7er02nkrezryq3ydtmkg0e7e2jvzg443h0ffzfwd09wpcxy2fuqmcnecd';
export const getAliceHandleProviderResponse = {
addresses: { cardano: aliceCardanoAddress },
backgroundImage: undefined,
cardanoAddress:
'addr_test1qqk4sr4f7vtqzd2w90d5nfu3n59jhhpawyphnek2y7er02nkrezryq3ydtmkg0e7e2jvzg443h0ffzfwd09wpcxy2fuqmcnecd',
cardanoAddress: aliceCardanoAddress,
handle: 'alice',
hasDatum: false,
image: Asset.Uri('ipfs://c8fc19c2e61bab6059bf8a466e6e754833a08a62a6c56feasd'),
policyId: Cardano.PolicyId('50fdcdbfa3154db86a87e4b5697ae30d272e0bbcfa8122efd3e301cb'),
profilePic: undefined
};

const bobCardanoAddress =
'addr_test1qzrljm7nskakjydxlr450ktsj08zuw6aktvgfkmmyw9semrkrezryq3ydtmkg0e7e2jvzg443h0ffzfwd09wpcxy2fuql9tk0g';
export const getBobHandleProviderResponse = {
addresses: { bitcoin: 'test_bitcoin_address', cardano: bobCardanoAddress },
backgroundImage: Asset.Uri('ipfs://zrljm7nskakjydxlr450ktsj08zuw6aktvgfkmmyw9semrkrezryq3yd'),
cardanoAddress:
'addr_test1qzrljm7nskakjydxlr450ktsj08zuw6aktvgfkmmyw9semrkrezryq3ydtmkg0e7e2jvzg443h0ffzfwd09wpcxy2fuql9tk0g',
cardanoAddress: bobCardanoAddress,
handle: 'bob',
hasDatum: false,
image: Asset.Uri('ipfs://c8fc19c2e61bab6059bf8a466e6e754833a08a62a6c56fe'),
Expand Down Expand Up @@ -99,7 +103,8 @@ export const getBobHandleAPIResponse: Partial<IHandle> = {
pfp_image: 'ipfs://zrljm7nskakjydxlr450ktsj08zuw6aktvgfkmmyw9semrkrezryq3yd1',
rarity: Rarity.rare,
resolved_addresses: {
ada: 'addr_test1qzrljm7nskakjydxlr450ktsj08zuw6aktvgfkmmyw9semrkrezryq3ydtmkg0e7e2jvzg443h0ffzfwd09wpcxy2fuql9tk0g'
ada: 'addr_test1qzrljm7nskakjydxlr450ktsj08zuw6aktvgfkmmyw9semrkrezryq3ydtmkg0e7e2jvzg443h0ffzfwd09wpcxy2fuql9tk0g',
btc: 'test_bitcoin_address'
},
standard_image: 'ipfs://c8fc19c2e61bab6059bf8a466e6e754833a08a62a6c56feasdfasd',
updated_slot_number: 22,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export class TypeOrmHandleProvider extends TypeormProvider implements HandleProv
]);

return {
addresses: { cardano: cardanoAddress },
backgroundImage: handleMetadataEntity?.backgroundImage || undefined,
cardanoAddress,
defaultForPaymentCredential: defaultForPaymentCredential || undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,15 @@ describe('HandleHttpService', () => {
});

it('valid not empty response is openApi schema compliant', async () => {
const cardanoAddress = <Cardano.PaymentAddress>'test_address';
await createServer({
getPolicyIds: () => Promise.resolve([<Cardano.PolicyId>'test_policy']),
healthCheck: () => Promise.resolve({ ok: true }),
resolveHandles: () =>
Promise.resolve([
{
cardanoAddress: <Cardano.PaymentAddress>'test_address',
addresses: { cardano: cardanoAddress },
cardanoAddress,
handle: 'test',
hasDatum: true,
policyId: <Cardano.PolicyId>'test_policy',
Expand All @@ -146,6 +148,7 @@ describe('HandleHttpService', () => {
expect({ body, status }).toEqual({
body: [
{
addresses: { cardano: 'test_address' },
cardanoAddress: 'test_address',
handle: 'test',
hasDatum: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import { NoCache, NodeTxSubmitProvider, NodeTxSubmitProviderProps } from '../../
import { generateRandomHexString } from '@cardano-sdk/util-dev';
import { dummyLogger as logger } from 'ts-log';

const cardanoAddress = Cardano.PaymentAddress(
'addr_test1qqk4sr4f7vtqzd2w90d5nfu3n59jhhpawyphnek2y7er02nkrezryq3ydtmkg0e7e2jvzg443h0ffzfwd09wpcxy2fuqmcnecd'
);
const mockHandleResolution = {
cardanoAddress: Cardano.PaymentAddress(
'addr_test1qqk4sr4f7vtqzd2w90d5nfu3n59jhhpawyphnek2y7er02nkrezryq3ydtmkg0e7e2jvzg443h0ffzfwd09wpcxy2fuqmcnecd'
),
addresses: { cardano: cardanoAddress },
cardanoAddress,
handle: 'alice',
hasDatum: false,
policyId: Cardano.PolicyId('50fdcdbfa3154db86a87e4b5697ae30d272e0bbcfa8122efd3e301cb'),
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/Provider/HandleProvider/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@ export type Handle = string;
* @param resolvedAt the point at which the Handle was resolved
*/
export interface HandleResolution {
addresses: {
bitcoin?: string;
cardano: Cardano.PaymentAddress;
};
policyId: Cardano.PolicyId;
handle: Handle;
/** @deprecated Use `addresses.cardano` instead. */
cardanoAddress: Cardano.PaymentAddress;
hasDatum: boolean;
defaultForStakeCredential?: Handle;
Expand Down
4 changes: 3 additions & 1 deletion packages/tx-construction/test/tx-builder/TxBuilder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ const rewardAccount2 = Cardano.RewardAccount('stake_test1up7pvfq8zn4quy45r2g5722
const rewardAccount3 = Cardano.RewardAccount('stake_test1uqehkck0lajq8gr28t9uxnuvgcqrc6070x3k9r8048z8y5gssrtvn');
const rewardAccount4 = Cardano.RewardAccount('stake_test17rphkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtcljw6kf');

const cardanoAddress = Cardano.PaymentAddress('addr_test1vr8nl4u0u6fmtfnawx2rxfz95dy7m46t6dhzdftp2uha87syeufdg');
const resolvedHandle = {
cardanoAddress: Cardano.PaymentAddress('addr_test1vr8nl4u0u6fmtfnawx2rxfz95dy7m46t6dhzdftp2uha87syeufdg'),
addresses: { cardano: cardanoAddress },
cardanoAddress,
handle: 'alice',
hasDatum: false,
policyId: Cardano.PolicyId('b0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a7'),
Expand Down
1 change: 1 addition & 0 deletions packages/wallet/src/services/HandlesTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export const createHandlesTracker = (
}
return {
...assetInfo,
addresses: { cardano: txOut.address },
cardanoAddress: txOut.address,
handle: Asset.util.getAssetNameAsText(handleAssetId),
hasDatum: !!txOut.datum
Expand Down
5 changes: 3 additions & 2 deletions packages/wallet/test/services/HandlesTracker.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const handleOutput = utxo.find(
)![1];

const expectedHandleInfo: HandleInfo = {
addresses: { cardano: handleOutput.address },
assetId: handleAssetId,
cardanoAddress: handleOutput.address,
fingerprint: handleFingerprint,
Expand Down Expand Up @@ -64,10 +65,10 @@ const hydrateHandle = (handleInfo: HandleInfo) =>

const exponentialBackoffDelay = (iteration: number) => Math.pow(2, iteration) * HYDRATE_HANDLE_INITIAL_INTERVAL;

const lastInteration = HYDRATE_HANDLE_MAX_RETRIES - 1;
const lastIteration = HYDRATE_HANDLE_MAX_RETRIES - 1;

const retrySyntax = (retries: number) =>
Array.from({ length: retries }, (_, i) => exponentialBackoffDelay(i) - (i === lastInteration ? 2 : 1))
Array.from({ length: retries }, (_, i) => exponentialBackoffDelay(i) - (i === lastIteration ? 2 : 1))
.map((exponentialDelay) => ` - ${exponentialDelay}ms `)
.join('');

Expand Down
Loading