[Webfunds-commits] java/webfunds/client/sox SOXWallet.java
Jeroen C. van Gelderen
gelderen@cypherpunks.ai
Thu, 6 Jul 2000 15:32:51 -0400 (AST)
gelderen 00/07/06 15:32:51
Modified: webfunds/client/sox SOXWallet.java
Log:
- Add makePurePayment that takes AccountIds instead of AccountInfos.
- Add doDeposit that tries to be as pure as possible (no GUI, no client code).
- Add mailItemToReceipt which does the obvious.
- Remove couple of hacks from makeDeposit, they've moved to their
own function (doDeposit).
- Add diagnostics.
- Pretty print diagnostics.
- Formatting fixes.
- Remove commented out code.
Revision Changes Path
1.126 +280 -101 java/webfunds/client/sox/SOXWallet.java
Index: SOXWallet.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/client/sox/SOXWallet.java,v
retrieving revision 1.125
retrieving revision 1.126
diff -u -r1.125 -r1.126
--- SOXWallet.java 2000/06/20 21:06:50 1.125
+++ SOXWallet.java 2000/07/06 19:32:50 1.126
@@ -1,7 +1,7 @@
-/* $Id: SOXWallet.java,v 1.125 2000/06/20 21:06:50 iang Exp $
+/* $Id: SOXWallet.java,v 1.126 2000/07/06 19:32:50 gelderen Exp $
*
- * Copyright (c) Systemics Ltd 1995-2000 on behalf of
- * the WebFunds Development Team. All Rights Reserved.
+ * Copyright (c) Systemics Inc. 1995-2000 on behalf of
+ * The WebFunds Development Team. All Rights Reserved.
*/
package webfunds.client.sox;
@@ -23,11 +23,9 @@
import webfunds.client.WalletContext;
import webfunds.client.WalletInterface;
import webfunds.client.sox.StoreAccountStore;
-
import webfunds.ricardian.Contract;
import webfunds.ricardian.ContractStore;
import webfunds.ricardian.SOXServerException;
-
import webfunds.sox.Account;
import webfunds.sox.AccountId;
import webfunds.sox.Armoury;
@@ -45,10 +43,8 @@
import webfunds.sox.SOXSubAccountException;
import webfunds.sox.SubAccount;
import webfunds.sox.ValueAccount;
-
import webfunds.store.Store;
import webfunds.store.StoreException;
-
import webfunds.utils.Debug;
import webfunds.utils.Hex;
import webfunds.utils.Panic;
@@ -56,6 +52,7 @@
/**
* The GUI Wallet.
+ *
* Needs to be rewritten into 2 wallets, a highlevel WebFunds GUI
* wallet and a low level SOX wallet that returns all info internally.
*
@@ -73,6 +70,9 @@
// these should probably be protected
public void error(String e)
{
+ if(e==null)
+ return;
+
logmsg("[ " + e + " ]");
context.getUInterface(this).errorMessage(e);
}
@@ -94,11 +94,10 @@
protected Store store;
protected ContractStore contracts = null;
protected Vector confirmmails = new Vector();
- //protected final WalletAction[] actions;
- protected static final String name = "SOX";
- protected String shortname = name;
- protected static final String fix = " SW: ";
+ protected static final String name = "SOX";
+ protected String shortname = name;
+ protected static final String fix = " SW: ";
protected static final String
try_again_later = "Try again later - cannot get through.",
@@ -114,17 +113,6 @@
public SOXWallet(PrintWriter bug) { super(); debug(bug, fix); }
public SOXWallet(PrintWriter bug, String f) { super(); debug(bug, f); }
-// Nah, done by SubAccount extension.
-// protected void addMine()
-// {
-// try {
-// EncryptedRequest.add("SOX.Deposit", "webfunds.sox.DepositRequest");
-// } catch (Exception ex) {
-// logmsg("adding SOX.Deposit: " + ex);
-// System.exit(1); // should throw die exception
-// }
-// }
-
/**
* Set the WalletContext.
@@ -242,7 +230,11 @@
//
try
{
+ System.err.println("Trying to get 'Accounts' store");
Store st = store.getStore("Accounts");
+ System.err.println(
+ " We got: " + st +
+ ", with size: " + st.size() );
StoreAccountStore accs;
accs = new StoreAccountStore(st, finder);
accs.debug(bug);
@@ -420,15 +412,12 @@
long amount, byte[] desc,
Date from, Date till)
{
- //AccountId target = new AccountId();
- //if (targetinfo != null)
- // target.setId(targetinfo.getId());
+ Payment pay = makePurePayment(source, targetinfo,
+ contractid, amount,
+ desc,
+ from.getTime(), till.getTime(),
+ null);
- Payment pay;
- pay = makePurePayment(source, targetinfo,
- contractid, amount,
- desc, from.getTime(), till.getTime(), null);
-
if (pay == null)
return null ;
@@ -452,6 +441,24 @@
}
+ public Payment makePurePayment(AccountId source, AccountId target,
+ ItemId instrument, long amount,
+ byte[] description,
+ long validFrom, long validTill,
+ String paymentId)
+ {
+ return makePurePayment(
+ new AccountInfo(source.getId(), null, null),
+ new AccountInfo(target.getId(), null, null),
+ instrument,
+ amount,
+ description,
+ validFrom,
+ validTill,
+ paymentId);
+ }
+
+
/**
* Make a payment.
* This should be used by all full service clients, it does:
@@ -519,8 +526,12 @@
if ( amount > 0 &&
- ((pend + confirmed) < amount || confirmed < amount))
+ ((pend + confirmed) < amount || confirmed < amount) )
{
+ System.err.print("amount: " + amount);
+ System.err.print(", pend: " + pend);
+ System.err.println(", confirmed: " + confirmed);
+
Contract contract = contracts.getContract(contractid);
double am = amount;
String name = contractid.toString();
@@ -529,12 +540,10 @@
am = contract.getAmount(amount);
name = contract.getName();
}
- String descString = Hex.printable(desc);
String q = "There is not enough for a payment of\n" +
"\n" +
- " " + am + " " + name + "\n" +
- " \"" + descString + "\"\n" +
+ " " + am + " " + name + "\n" +
"\n" +
"and it may bounce when deposited!\n\n\n" +
"Are you sure you want to make this payment?";
@@ -612,16 +621,6 @@
public void makeDeposit(byte[] payment, AccountInfo callerAc, byte[] desc)
{
- makeDeposit(payment, callerAc, desc, true);
- }
-
-
- /**
- * Client Wallet Interface
- */
- public void makeDeposit(byte[] payment, AccountInfo callerAc, byte[] desc,
- boolean useAddressBook)
- {
byte[] buf = decodeSOXPayment(payment);
if (buf == null)
{
@@ -660,6 +659,8 @@
{
if (pt.isBearer())
{
+ logmsg("pt.isBearer() says 'true'");
+
// Ok, so it's bearer, and we can deposit it anywhere.
ac = getAccount(callerAc);
@@ -839,9 +840,6 @@
}
- if( useAddressBook )
- {
-
byte[] srcId = pss.getId(); // already checked
AccountInfo source;
source = context.getAddressbook(this).getInfo(srcId);
@@ -865,12 +863,208 @@
aviso("Deposit from " + name + " is Good:\n" + statString);
- } // useAddressBook
internalUpdate(sub, mails);
return ;
}
+ private String _func;
+ private void ENTER(String s) { this._func = s; }
+ private void TRACE(String s)
+ {
+ System.err.println( "Wallet." + this._func + ": " + s );
+ }
+
+
+ /**
+ * Deposit the given payment.
+ *
+ * If the Payment is a bearer payment it is deposited in targetAccount.
+ * If not, targetAccount must be null.
+ *
+ * If the Payment
+ */
+ public Receipt doDeposit(
+ Payment payment,
+ AccountId accountToUse,
+ byte[] desc)
+ throws DepositException
+ {
+ ENTER("doDeposit");
+ TRACE("payment=" + payment +
+ ", accountToUse=" + accountToUse +
+ ", desc=" + desc );
+
+ Payment pay = payment;
+
+ AccountId ptt = pay.getTarget();
+ AccountId pss = pay.getSource();
+
+ AccountInfo callerAc=new AccountInfo(accountToUse.getId(), null, null);
+ AccountInfo ps =new AccountInfo(pss.getId(), null, null);
+ AccountInfo pt =new AccountInfo(ptt.getId(), null, null);
+
+ String pid = pay.getId();
+
+
+ //
+ // Acquire the account which does the deposit.
+ // This might not be a participant in the activity.
+ // Which makes it terribly complex.
+ // Maybe this should be banned, or another flexible
+ // interface provided.
+ //
+ Account ac;
+ boolean knownAccount = true; // following code should work, except...
+ try
+ {
+ if (pt.isBearer())
+ {
+ System.err.println("it's a bearer payment!");
+ // Ok, so it's bearer, and we can deposit it anywhere.
+ ac = getAccount(callerAc);
+
+ if (ac == null)
+ throw new RuntimeException("no target for bearer");
+
+ // this is who we are going to deposit the bearer into
+ ptt = ac.getId();
+ pt = new AccountInfo(ptt.getId(), null, this);
+ knownAccount = true;
+ }
+ else
+ {
+ System.err.println("JCvG: it's not a bearer payment");
+ //
+ // We need to acquire an account, so as to get a
+ // subaccount, so as to do a deposit. It doesn't
+ // actually make much difference which sub account
+ // does the deposit, as the issuer checks that the
+ // payment is good, not the deposit (unless bearer).
+ // But, it's nice for the receipt if it is all
+ // aligned.
+ //
+ // was this back to front? Should look at target first...
+ ac = getAccount(ps);
+ if (ac == null) // not our target
+ {
+ ac = getAccount(pt);
+ if(ac == null)
+ throw new DepositException(
+ DepositException.UNKNOWN_ACCOUNT);
+ }
+ }
+ }
+ catch (StoreException ex)
+ {
+ ex.printStackTrace();
+ error("cannot recover accounts? " + ex);
+ throw new RuntimeException("Dunno, looks very wrong");
+ }
+
+
+ String choice = ac.getName();
+ logmsg("ready to deposit payment using " + choice + "\n" + pay);
+ if (desc == null)
+ desc = new byte[0];
+
+ //
+ // When we grab the subaccount, record if it doesn't exists,
+ // so we can add it later to the store.
+ //
+ ItemId item = pay.getItem();
+ boolean makeNewSub = false;
+ ValueAccount sub = (ValueAccount) ac.getSub(item);
+ if (sub == null)
+ {
+ makeNewSub = true; // only if our account...
+ sub = new ValueAccount(item);
+ try {
+ ac.newSub(sub);
+ } catch (SOXSubAccountException ex) {
+ ex.printStackTrace();
+ error("cannot create SubAccount: " + ex);
+ throw new RuntimeException("cannot create subAccount");
+ } catch (SOXAccountException ex) {
+ ex.printStackTrace();
+ error("Account error: " + ex);
+ throw new RuntimeException("Account error: " + ex);
+ }
+ }
+
+ MailItem[] mails;
+ try {
+ mails = sub.deposit(pay, new String(desc));
+ } catch (SOXLaterException ex) {
+ throw new RuntimeException("later!");
+ } catch (SOXSubAccountException e) {
+ e.printStackTrace();
+ throw new DepositException(e.getNumber());
+ } catch (SOXException ex) {
+ throw new DepositException(DepositException.INSUFFICIENT_FUNDS);
+ }
+
+ logmsg("received mails: " + mails.length);
+
+ //
+ // By convention, if mails are returned, 1st one is
+ // the one for this deposit.
+ // Others are for the (sub?) account.
+ // (Actually, as implemented, there is only one mail.)
+ //
+ if (mails == null)
+ throw new RuntimeException(
+ "Deposit partial (no mail returned) try an update...");
+
+ String s = checkReceipt(mails[0], pss, ptt, item, pay.getQty());
+ if (s != null)
+ throw new RuntimeException("cancel receipt is not good: " + s);
+
+ if (makeNewSub && !knownAccount) // only if our account...
+ {
+ // I think this is right.
+ aviso("Deposit is complete.\n\nAs the account is unknown,\nignoring mail and subs");
+ throw new RuntimeException("Account unknown???");
+ }
+
+ String statString = "";
+ //
+ // Some admin
+ // - make a new sub by re-adding the account if needed.
+ // - get a name for a new source account.
+ //
+ if (makeNewSub)
+ {
+ //
+ // The getSub() did all the account work,
+ // now just need to store it.
+ //
+ try {
+ accountStore.addAccount(ac);
+ } catch (StoreException ex) {
+ ex.printStackTrace(System.err);
+ logmsg("account " + ac + " sub " + sub);
+ logmsg("cannot add subaccount? " + ex);
+ System.exit(1);
+ }
+ aviso("Hmmm. That worked, and created a new subaccount...\n" +
+ "which you can't see :( What you need is a workaround:" +
+ "\n\nTo see the contract, hit [Add Contract] on this:" +
+ "\n\n" + item + "\n\n" +
+ "(as there is no way to tell the GUI what to do here!)");
+ statString += "\n (subAccount made in " + ac + ")";
+ }
+
+
+ internalUpdate(sub, mails);
+
+ Receipt rcpt = mailItemToReceipt( mails[0] );
+ if( rcpt == null )
+ throw new DepositException(DepositException.NO_RECEIPT);
+ else
+ return rcpt;
+ }
+
/**
@@ -892,7 +1086,25 @@
return checkReceipt(receipt, p_src, p_tgt, p_item, amount);
}
+
/**
+ * Convert a MailItem to Receipt.
+ *
+ * @return Receipt or null
+ */
+ private Receipt mailItemToReceipt(MailItem mailItem)
+ {
+ try
+ {
+ return new Receipt( mailItem.getMessage() );
+ }
+ catch(SOXPacketException e1)
+ {
+ return null;
+ }
+ }
+
+ /**
* Check the receipt conforms to what was expected.
* @return an error string if not conformant, else null
*/
@@ -996,6 +1208,7 @@
cancel(sub, pid);
}
+
/**
* Cancel a Payment (pid) within a SubAccount.
* And call the update. This can be used by other wallets.
@@ -1134,6 +1347,7 @@
return ;
}
+
/**
* Cancel a Payment (pid) within a SubAccount.
*
@@ -1183,6 +1397,7 @@
throw new RuntimeException("not implemented");
}
+
/**
* Cancel a Payment (pid) within a SubAccount.
* This can be used by other wallets, but be
@@ -1232,8 +1447,8 @@
}
-
/////////// Account / Contract manipulations ////////////////////////
+
public AccountInfo addAccount()
{
@@ -1438,20 +1653,7 @@
sub.freeze();
-// ByteArrayOutputStream baos = new ByteArrayOutputStream();
-// try {
-// account.encode(baos);
-// byte[] b = baos.toByteArray();
-// logmsg("converting " + b.length + " bytes");
-// Account ac = new Account(b);
-// } catch (Exception ex) {
-// logmsg("sunk " + ex);
-// ex.printStackTrace();
-// System.exit(1);
-// }
-
- try
- {
+ try {
accountStore.addAccount(account); // restorage saves freeze
} catch (StoreException ex) {
ex.printStackTrace();
@@ -1512,6 +1714,7 @@
return true;
}
+
/**
* Client Wallet Interface
*/
@@ -1611,6 +1814,7 @@
manyUpdates(sub, null); // sub is surrogate for account
}
+
/**
* Make an AccountInfo for this sub account.
* Gets the account, then the id.
@@ -1622,6 +1826,7 @@
return new AccountInfo(id.getId(), null, this);
}
+
/**
* Make an AccountId for this sub account.
* Gets the account, then the id.
@@ -1633,6 +1838,7 @@
return ac.getId();
}
+
/**
* Handle this mail that came via another request
* or another subaccount.
@@ -1647,6 +1853,7 @@
manyUpdates(sub, mails);
}
+
protected void internalUpdate(SubAccount sub, MailItem mail)
{
MailItem[] mm = new MailItem[1];
@@ -1654,6 +1861,7 @@
manyUpdates(sub, mm);
}
+
/**
* Get and sign for the mail from the issuer for this account.
*/
@@ -1694,6 +1902,7 @@
throw new RuntimeException("too many: mail appears to be spinning");
}
+
/**
* Do an update - one single cycle of request with sigs.
* Bummer. There is a problem here. Mail is requested
@@ -1714,8 +1923,9 @@
try
{
mails = sub.update(confirms);
- } catch (SOXLaterException e) {
-
+ }
+ catch (SOXLaterException e)
+ {
// Yeah, this real wrong. Need to handle errors silently.
// hmm, caller might not want a popup. How to handle?
@@ -1733,11 +1943,11 @@
return mails ;
}
+
/**
* Do an update - one single cycle of request with sigs.
*/
- protected MailId[] tryHandle(SubAccount sub,
- MailItem[] mails)
+ protected MailId[] tryHandle(SubAccount sub, MailItem[] mails)
{
Vector newConfirms = new Vector();
@@ -1785,12 +1995,12 @@
return ok ;
}
+
/**
* For some reason, Receipts are stored on an account basis.
*/
public boolean handleReceiptData(byte[] recdata, AccountId acct)
{
-
Receipt rec = null;
try {
rec = new Receipt(recdata);
@@ -1801,9 +2011,10 @@
return false ;
}
logmsg("Receipt : " + rec);
- return handleReceipt(rec, acct);
+ return handleReceipt(rec, acct);
}
+
public boolean handleReceipt(Receipt rec, AccountId acct)
{
try {
@@ -1845,7 +2056,6 @@
{
Receipt[] receipts;
PendingReceipt[] pendings;
- //AccountId account = getId(info);
AccountId acct = new AccountId();
acct.setId(info.getId());
@@ -1928,39 +2138,8 @@
}
-// /**
-// * Unused.
-// */
-// public Transaction getPaymentStatus(byte[] paymentdata)
-// {
-// try
-// {
-// byte[] thing = Armoury.decode(new String(paymentdata));
-// Payment pay = new Payment(thing);
-// byte[] src = pay.getSource().getId();
-// AccountInfo info = new AccountInfo(src, null, null);
-// context.getAddressbook(this).updateInfo(info);
-// Transaction[] trans = getTransactions(info, pay.getItem());
-// String id = pay.getId();
-// for (int i = 0; i < trans.length; i++)
-// {
-// if (trans[i].getTransId().equals(id))
-// return trans[i];
-// }
-// }
-// catch (Exception ex)
-// {
-// error("get status failed: " + ex);
-// }
-// return null;
-// }
-
-
-
public String toString()
{
return shortname;
}
-
-
}