Skip to content

Commit ba0eee5

Browse files
authored
Merge pull request #140 from MeshJS/bug/external-stake-credential
feat(wallet): enhance wallet signers information and script type hand…
2 parents 119cb40 + 8d8e6b3 commit ba0eee5

File tree

6 files changed

+61
-8
lines changed

6 files changed

+61
-8
lines changed

src/components/pages/homepage/wallets/new-wallet-flow/create/ReviewRequiredSignersCard.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,26 @@ const ReviewRequiredSignersCard: React.FC<ReviewRequiredSignersCardProps> = ({
166166
})()}
167167
</span>
168168
</div>
169+
170+
{/* Info message for "all" and "any" script types */}
171+
{(nativeScriptType === 'all' || nativeScriptType === 'any') && (
172+
<div className="flex items-start gap-2 p-3 bg-blue-50 dark:bg-blue-950/20 rounded-lg">
173+
<svg className="w-4 h-4 mt-0.5 flex-shrink-0 text-blue-600 dark:text-blue-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
174+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
175+
</svg>
176+
<div className="text-xs text-blue-800 dark:text-blue-200">
177+
<p className="font-medium mb-1">
178+
{nativeScriptType === 'all' ? 'All Signers Required' : 'Any Signer Can Approve'}
179+
</p>
180+
<p>
181+
With "{nativeScriptType === 'all' ? 'All' : 'Any'}" script type, no specific number is stored.
182+
{nativeScriptType === 'all'
183+
? ' Every signer must approve each transaction.'
184+
: ' Any single signer can approve each transaction.'}
185+
</p>
186+
</div>
187+
</div>
188+
)}
169189
{/* Edit button - only show for atLeast type */}
170190
{nativeScriptType === "atLeast" && (
171191
<div className="pt-2">

src/components/pages/homepage/wallets/new-wallet-flow/shared/useWalletFlowState.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ export function useWalletFlowState(): WalletFlowState {
158158
numRequiredSigners,
159159
network,
160160
stakeKey || undefined,
161+
nativeScriptType,
161162
);
162163
}, [
163164
name,
@@ -168,6 +169,7 @@ export function useWalletFlowState(): WalletFlowState {
168169
numRequiredSigners,
169170
network,
170171
stakeKey,
172+
nativeScriptType,
171173
]);
172174

173175
// API Mutations

src/components/pages/wallet/info/signers/card-signers.tsx

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,30 @@ export default function CardSigners({ appWallet }: { appWallet: Wallet }) {
2020
title="Signers"
2121
description={
2222
<>
23-
This wallet requires{" "}
24-
<b className="text-foreground">{appWallet.numRequiredSigners}</b> signers{" "}
25-
to sign a transaction.
23+
{(() => {
24+
const signersCount = appWallet.signersAddresses.length;
25+
if (appWallet.type === 'all') {
26+
return (
27+
<>
28+
<b className="text-foreground">All signers</b> (of {signersCount}) must approve each transaction.
29+
</>
30+
);
31+
} else if (appWallet.type === 'any') {
32+
return (
33+
<>
34+
<b className="text-foreground">Any signer</b> (of {signersCount}) can approve each transaction.
35+
</>
36+
);
37+
} else {
38+
return (
39+
<>
40+
This wallet requires{" "}
41+
<b className="text-foreground">{appWallet.numRequiredSigners}</b> of {signersCount} signers{" "}
42+
to sign a transaction.
43+
</>
44+
);
45+
}
46+
})()}
2647
</>
2748
}
2849
headerDom={

src/hooks/common.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export function buildMultisigWallet(
5858
wallet.numRequiredSigners ?? 1,
5959
network,
6060
wallet.stakeCredentialHash ?? undefined,
61+
(wallet.type as "all" | "any" | "atLeast") ?? "atLeast",
6162
);
6263
return multisigWallet;
6364
}

src/server/api/routers/wallets.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,15 @@ export const walletRouter = createTRPCRouter({
4343
}),
4444
)
4545
.mutation(async ({ ctx, input }) => {
46+
const numRequired = (input.type === "all" || input.type === "any") ? null : input.numRequiredSigners;
4647
return ctx.db.wallet.create({
4748
data: {
4849
name: input.name,
4950
description: input.description,
5051
signersAddresses: input.signersAddresses,
5152
signersDescriptions: input.signersDescriptions,
5253
signersStakeKeys: input.signersStakeKeys,
53-
numRequiredSigners: input.numRequiredSigners,
54+
numRequiredSigners: numRequired as any,
5455
scriptCbor: input.scriptCbor,
5556
stakeCredentialHash: input.stakeCredentialHash,
5657
type: input.type,
@@ -168,14 +169,15 @@ export const walletRouter = createTRPCRouter({
168169
}),
169170
)
170171
.mutation(async ({ ctx, input }) => {
172+
const numRequired = (input.scriptType === "all" || input.scriptType === "any") ? null : input.numRequiredSigners;
171173
return ctx.db.newWallet.create({
172174
data: {
173175
name: input.name,
174176
description: input.description,
175177
signersAddresses: input.signersAddresses,
176178
signersDescriptions: input.signersDescriptions,
177179
signersStakeKeys: input.signersStakeKeys,
178-
numRequiredSigners: input.numRequiredSigners,
180+
numRequiredSigners: numRequired as any,
179181
ownerAddress: input.ownerAddress,
180182
stakeCredentialHash: input.stakeCredentialHash,
181183
scriptType: input.scriptType,
@@ -198,6 +200,7 @@ export const walletRouter = createTRPCRouter({
198200
}),
199201
)
200202
.mutation(async ({ ctx, input }) => {
203+
const numRequired = (input.scriptType === "all" || input.scriptType === "any") ? null : input.numRequiredSigners;
201204
return ctx.db.newWallet.update({
202205
where: {
203206
id: input.walletId,
@@ -208,7 +211,7 @@ export const walletRouter = createTRPCRouter({
208211
signersAddresses: input.signersAddresses,
209212
signersDescriptions: input.signersDescriptions,
210213
signersStakeKeys: input.signersStakeKeys,
211-
numRequiredSigners: input.numRequiredSigners,
214+
numRequiredSigners: numRequired as any,
212215
stakeCredentialHash: input.stakeCredentialHash,
213216
scriptType: input.scriptType,
214217
} as any,

src/utils/multisigSDK.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ export class MultisigWallet {
144144
network: number;
145145
/** Optional external stake credential hash (28-byte hex string) */
146146
stakeCredentialHash: string | undefined;
147+
/** Script type: "all", "any", or "atLeast" */
148+
type: "all" | "any" | "atLeast";
147149

148150
/**
149151
* Creates a new MultisigWallet instance.
@@ -154,6 +156,7 @@ export class MultisigWallet {
154156
* @param required - Number of signatures required (default: 1)
155157
* @param network - Network identifier: 0=testnet, 1=mainnet (default: 1)
156158
* @param stakeCredentialHash - Optional external stake credential hash (28-byte hex string)
159+
* @param type - Script type: "all", "any", or "atLeast" (default: "atLeast")
157160
*
158161
* @throws {Error} If no valid payment keys are provided
159162
*
@@ -175,7 +178,8 @@ export class MultisigWallet {
175178
* "Wallet with staking capabilities",
176179
* 2, // require 2 signatures
177180
* 0, // testnet
178-
* "external_stake_credential_hash"
181+
* "external_stake_credential_hash",
182+
* "all" // all signers must approve
179183
* );
180184
* ```
181185
*/
@@ -186,6 +190,7 @@ export class MultisigWallet {
186190
required?: number,
187191
network?: number,
188192
stakeCredentialHash?: string,
193+
type: "all" | "any" | "atLeast" = "atLeast",
189194
) {
190195
this.name = name;
191196
// Filter out any keys that are not valid
@@ -200,6 +205,7 @@ export class MultisigWallet {
200205
this.required = required ? required : 1;
201206
this.network = network !== undefined ? network : 1;
202207
this.stakeCredentialHash = stakeCredentialHash;
208+
this.type = type;
203209
}
204210

205211
/**
@@ -339,7 +345,7 @@ export class MultisigWallet {
339345
const filteredKeys = this.getKeysByRole(role);
340346
if (!filteredKeys) return undefined;
341347
// Build the script using only the keys of the specified role
342-
return buildNativeScript(filteredKeys, this.required);
348+
return buildNativeScript(filteredKeys, this.required, this.type);
343349
}
344350

345351
/**

0 commit comments

Comments
 (0)